rendered paste body/*
* Asterisk -- A telephony toolkit for Linux.
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
* Version: 2.1.1 - 07/3/05
*
* Clod Patry <cpatry@gmail.com> for inner usage
*/
#include <asterisk/lock.h>
#include <asterisk/file.h>
#include <asterisk/pbx.h>
#include <asterisk/module.h>
#include <asterisk/translate.h>
#include <asterisk/utils.h>
#include <sys/types.h>
#include <asterisk/config.h>
#include <asterisk/options.h>
#include <asterisk/channel.h>
#include <asterisk/cdr.h>
#include <asterisk/module.h>
#include <asterisk/logger.h>
#include "../asterisk.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <libpq-fe.h>
int limit_achieved(struct ast_channel *chan, char *argument);
char* get_action(char *app_id);
static char *synopsis = "Check Blacklist";
static char *app = "CheckBlacklist";
static char *tdesc = "Check Blacklist";
static char *descrip = "Usage: CheckBlacklist(app_id[,iso_country])\n"
" To see if a specific caller_id is on a blacklist in our systems\n"
" If yes, it's fetch his application.cid_action\n"
" Otherwise, it will go at priority N+1\n"
" iso_country is the iso code for a specific country, if not specified, 'ca' will be used.\n";
static char *config = "cdr_pgsql.conf";
static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword = NULL, *pgdbsock = NULL, *pgdbport = NULL;
static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbport_alloc = 0;
//static int dbsock_alloc = 0;
static int connected = 0;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
PGconn *conn;
PGresult *result;
static void wait_for_hangup(struct ast_channel *chan, void *data)
{
int res;
struct ast_frame *f;
int waittime;
if (!data || !strlen(data) || (sscanf(data, "%i", &waittime) != 1) || (waittime < 0))
waittime = -1;
if (waittime > -1) {
ast_safe_sleep(chan, waittime * 1000);
} else do {
res = ast_waitfor(chan, -1);
if (res < 0)
return;
f = ast_read(chan);
if (f)
ast_frfree(f);
} while(f);
}
static int my_load_config(void){
/* Connection to the database */
struct ast_config *cfg_file;
struct ast_variable *var;
char *tmp;
cfg_file = ast_load(config);
if (!cfg_file) {
ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config);
return 0;
}
var = ast_variable_browse(cfg_file, "global");
if (!var) {
// nothing configured
return 0;
}
tmp = ast_variable_retrieve(cfg_file,"global","hostname");
if (tmp) {
pghostname = malloc(strlen(tmp) + 1);
if (pghostname != NULL) {
memset(pghostname, 0, strlen(tmp) + 1);
hostname_alloc = 1;
strncpy(pghostname, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL server hostname not specified. Assuming localhost\n");
pghostname = "localhost";
}
tmp = ast_variable_retrieve(cfg_file,"global","dbname");
if (tmp) {
pgdbname = malloc(strlen(tmp) + 1);
if (pgdbname != NULL) {
memset(pgdbname, 0, strlen(tmp) + 1);
dbname_alloc = 1;
strncpy(pgdbname, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database not specified. Assuming asterisk\n");
pgdbname = "asteriskcdrdb";
}
tmp = ast_variable_retrieve(cfg_file,"global","user");
if (tmp) {
pgdbuser = malloc(strlen(tmp) + 1);
if (pgdbuser != NULL) {
memset(pgdbuser, 0, strlen(tmp) + 1);
dbuser_alloc = 1;
strncpy(pgdbuser, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database user not specified. Assuming root\n");
pgdbuser = "root";
}
tmp = ast_variable_retrieve(cfg_file,"global","password");
if (tmp) {
pgpassword = malloc(strlen(tmp) + 1);
if (pgpassword != NULL) {
memset(pgpassword, 0, strlen(tmp) + 1);
password_alloc = 1;
strncpy(pgpassword, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database password not specified. Assuming blank\n");
pgpassword = "";
}
tmp = ast_variable_retrieve(cfg_file,"global","port");
if (tmp) {
pgdbport = malloc(strlen(tmp) + 1);
if (pgdbport != NULL) {
memset(pgdbport, 0, strlen(tmp) + 1);
dbport_alloc = 1;
strncpy(pgdbport, tmp, strlen(tmp));
} else {
ast_log(LOG_ERROR,"Out of memory error.\n");
return -1;
}
} else {
ast_log(LOG_WARNING,"PostgreSQL database port not specified. Using default 5432.\n");
pgdbport = "5432";
}
ast_destroy(cfg_file);
return 1;
}
static int checkblacklist_exec(struct ast_channel *chan, void *data)
{
char sqlcmd[200];
char *pgerror;
int count = 0;
char *cid_num = chan->cid.cid_num;
char *option;
char *app_id;
if ( !data ) {
ast_log(LOG_WARNING, "1.CheckBlacklist requires an argument (app_id)\n");
return -1;
}
if (ast_strlen_zero((char *) data)) {
ast_log(LOG_WARNING, "CheckBlacklist requires an argument (app_id)\n");
return -1;
}
if (!(app_id = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Unable to dupe data :(\n");
return -1;
}
option = strchr(app_id, '|');
if (option) {
*option = '\0';
option++;
}
ast_log(LOG_WARNING, "app_id=%s\n",app_id);
//ast_log(LOG_WARNING, "caller_id = %s\n", cid_num);
if (pgdbsock)
ast_log(LOG_DEBUG,"cdr_pgsql: got sock file of %s\n",pgdbsock);
conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword);
if (PQstatus(conn) != CONNECTION_BAD) {
//ast_log(LOG_WARNING,"Successfully connected to PostgreSQL database.\n");
connected = 1;
} else {
pgerror = PQerrorMessage(conn);
ast_log(LOG_WARNING, "CheckBlacklist: Unable to connect to database server %s.\n", pghostname);
ast_log(LOG_WARNING, "CheckBlacklist: Reason: %s.\n", pgerror);
connected = 0;
PQfinish(conn);
return 0;
}
if ( !conn ) {
ast_log(LOG_WARNING, "CheckBlacklist: NO CONNECTION\n");
}
if ( !cid_num ) {
ast_log(LOG_WARNING, "NO CID_NUM => caller_id = %s\n", cid_num);
sprintf(sqlcmd, "SELECT cid_action FROM application WHERE application_id='%s' AND active='TRUE'",app_id);
ast_log(LOG_WARNING, "no_cid => query=%s\n",sqlcmd);
result = PQexec(conn,sqlcmd);
ast_log(LOG_WARNING, "%d results\n",PQntuples(result) );
char *action;
if ( PQntuples(result) > 0 ) {
action = PQgetvalue(result,0,0);
} else {
ast_log(LOG_NOTICE, "Check the arguments of CheckBlacklist() of app_id=%s\n",app_id);
PQclear(result);
PQfinish(conn);
limit_achieved(chan, "BUSY");
return -1;
}
PQclear(result);
if ( action ) {
ast_log(LOG_WARNING, "no CID; action=%s\n",action);
PQfinish(conn);
if ( limit_achieved(chan, action) ) {
return -1;
}
}
}
char *country_code = "ca";
sprintf(sqlcmd, "SELECT COUNT(*) FROM blacklist WHERE caller_id='%s' AND application_id=0 AND country='%s';", cid_num, country_code);
ast_log(LOG_WARNING, "query=%s\n",sqlcmd);
result = PQexec(conn,sqlcmd);
count = atoi(PQgetvalue(result,0,0));
PQclear(result);
PQfinish(conn);
//ast_log(LOG_WARNING, "answer = %d\n",count);
if ( count < 1 ) {
//ast_log(LOG_WARNING, "%s is not blacklisted ...continue\n",(char *)data);
return 0;
} else {
ast_log(LOG_WARNING, "%s is blacklisted!!\n", (char *)data);
if (chan->cdr && data) {
ast_cdr_appenduserfield(chan, "call=blacklist");
}
ast_indicate(chan, AST_CONTROL_BUSY);
wait_for_hangup(chan, "16");
return -1;
}
}
char* get_action(char *app_id) {
return "vm-intro";
}
int limit_achieved(struct ast_channel *chan, char *action) {
ast_log(LOG_DEBUG, "in limit_achieved arg = %s\n", action);
if ( chan->cdr ) {
ast_cdr_appenduserfield(chan, "call=blacklist");
}
if ( !strcmp(action,"BUSY") ) {
ast_log(LOG_WARNING, "action is BUSY\n");
ast_indicate(chan, AST_CONTROL_BUSY);
wait_for_hangup(chan, action);
} else if ( !strcmp(action,"HANGUP") ) {
ast_log(LOG_WARNING, "action is HANGUP\n");
} else if ( !strcmp(action,"") ) {
ast_log(LOG_WARNING, "action is Nothing, set it to BUSY\n");
ast_indicate(chan, AST_CONTROL_BUSY);
wait_for_hangup(chan, action);
} else {
ast_log(LOG_WARNING, "action is STREAM\n");
//Streaming this file
int res = ast_streamfile(chan, action, chan->language);
res = ast_waitstream(chan, "");
}
return -1;
}
int unload_module(void)
{
STANDARD_HANGUP_LOCALUSERS;
return ast_unregister_application(app);
}
int load_module(void)
{
/* Loading config file once */
my_load_config();
return ast_register_application(app, checkblacklist_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}