/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) <2009>, * * <> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. */ //TODO: confif file should be cached in memory /*! \file * * \brief Skeleton application * * \author <> * * This is a skeleton for development of an Asterisk application * \ingroup applications */ /*** MODULEINFO no ***/ /** This app will first look in filter.conf, under the general section to see what kind of DB it should use [general] dbtype=0 if dbtype == 0, filter.conf will be used if dbtype == 1, mysql will be used if filter.conf is used, the following format must be used: [test1] ; or whatever you want to call it cid => 123456789 cid => 129889789 ; list of numbers that belong to that section greeting => test1 ; if defined, that greeting will be played. DO NOT SPECIFY THE EXTENSION OF THE FILE exten => 3 ; if exten and context are defined, the call will be redirected to that extension. If not defined, dialplan execution will continue context => context1 if the number is not found in any section, dialplan execution continues **/ #define FILTER_CONFIG "filter.conf" #define DBTYPE_FILE 0 #define DBTYPE_MYSQL 1 #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision: 40722 $") #include #include #include #include #include "asterisk/file.h" #include "asterisk/logger.h" #include "asterisk/channel.h" #include "asterisk/pbx.h" #include "asterisk/module.h" #include "asterisk/lock.h" #include "asterisk/app.h" static char *app = "Filter"; static char *synopsis = "Filter application."; static char *descrip = "This application is a template to build other applications from.\n" " It shows you the basic structure to create your own Asterisk applications.\n"; enum { OPTION_A = (1 << 0), OPTION_B = (1 << 1), OPTION_C = (1 << 2), } option_flags; enum { OPTION_ARG_B = 0, OPTION_ARG_C = 1, /* This *must* be the last value in this enum! */ OPTION_ARG_ARRAY_SIZE = 2, } option_args; AST_APP_OPTIONS(app_opts,{ AST_APP_OPTION('a', OPTION_A), AST_APP_OPTION_ARG('b', OPTION_B, OPTION_ARG_B), AST_APP_OPTION_ARG('c', OPTION_C, OPTION_ARG_C), }); struct FilterClass{ char greeting[256]; char exten[256]; char context[256]; }; static int findFilterFromConfig(struct ast_config *cfg, char* cid, struct FilterClass *fc); static int app_exec(struct ast_channel *chan, void *data) { int res = 0; struct ast_flags flags; char filterclass[256] = "0"; struct ast_module_user *u; struct ast_config *cfg; int dbtype = DBTYPE_FILE; char *parse, *opts[OPTION_ARG_ARRAY_SIZE]; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(dummy); AST_APP_ARG(options); ); u = ast_module_user_add(chan); parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); if (args.argc == 2){ ast_app_parse_options(app_opts, &flags, opts, args.options); } // Parse the config file cfg = ast_config_load(FILTER_CONFIG); if (!cfg) { ast_log(LOG_WARNING, "No such configuration file %s\n", FILTER_CONFIG); ast_module_user_remove(u); return -1; } dbtype = atoi(ast_variable_retrieve(cfg, "general", "dbtype")); struct FilterClass fc; fc.greeting[0] = 0; fc.exten[0] = 0; fc.context[0] = 0; int found = 0; switch (dbtype){ case DBTYPE_FILE: ast_log(LOG_NOTICE, "Using %s as database file\n",FILTER_CONFIG); found = findFilterFromConfig(cfg,chan->cid.cid_num,&fc); break; case DBTYPE_MYSQL: //TODO: must use mysqlDB. But allow to compile even if mysql not installed (using ifdef) ast_log(LOG_NOTICE, "Using MySQL as database\n"); break; default: ast_log(LOG_WARNING, "Incorect database type %i\n", dbtype); break; } //TODO: Should Answer() if not already done in the diaplan if (found){ if (fc.greeting[0] != 0){ // Play a greeting ast_play_and_wait(chan, &fc.greeting); } if ((fc.exten[0] != 0) && (fc.context[0] != 0)){ // jump to context:exten ast_goto_if_exists(chan, fc.context, fc.exten, 1); } //pbx_builtin_setvar_helper(chan, "FILTERCLASS", fc.greeting); } ast_module_user_remove(u); return res; } static int findFilterFromConfig(struct ast_config *cfg, char* cid, struct FilterClass *fc) { char *context=0; char *exten = 0; char *greeting=0; int found = 0; char *cat = 0; struct ast_variable *var; while ((cat = ast_category_browse(cfg, cat)) ) { context = 0; exten = 0; greeting = 0; if (!strcasecmp(cat, "general")) { } else { for (var = ast_variable_browse(cfg, cat); var; var = var->next) { if (!strcasecmp(var->name, "cid")){ if (!strcasecmp(var->value, cid)) found = 1; } else if (!strcasecmp(var->name, "greeting")){ greeting = var->value; } else if (!strcasecmp(var->name, "exten")){ exten = var->value; } else if (!strcasecmp(var->name, "context")){ context = var->value; } } if (found){ if (context) strcpy(fc->context,context); if (exten) strcpy(fc->exten,exten); if (greeting) strcpy(fc->greeting,greeting); return 1; } } } return 0; } static int unload_module(void) { int res; res = ast_unregister_application(app); return res; } static int load_module(void) { return ast_register_application(app, app_exec, synopsis, descrip); } AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Filter calls based on callerID");