Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:48 2009

## Asterisk developer's documentation

# app_privacy.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  *
    00021  * \brief Block all calls without Caller*ID, require phone # to be entered
    00022  *
    00023  * \ingroup applications
    00024  */
    00025
    00026 #include <stdlib.h>
    00027 #include <stdio.h>
    00028 #include <string.h>
    00029
    00030 #include "asterisk.h"
    00031
    00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
    00033
    00034 #include "asterisk/lock.h"
    00035 #include "asterisk/file.h"
    00036 #include "asterisk/utils.h"
    00037 #include "asterisk/logger.h"
    00038 #include "asterisk/options.h"
    00039 #include "asterisk/channel.h"
    00040 #include "asterisk/pbx.h"
    00041 #include "asterisk/module.h"
    00042 #include "asterisk/translate.h"
    00043 #include "asterisk/image.h"
    00044 #include "asterisk/callerid.h"
    00045 #include "asterisk/app.h"
    00046 #include "asterisk/config.h"
    00047
    00048 #define PRIV_CONFIG "privacy.conf"
    00049
    00050 static char *tdesc = "Require phone number to be entered, if no CallerID sent";
    00051
    00052 static char *app = "PrivacyManager";
    00053
    00054 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
    00055
    00056 static char *descrip =
    00057   "  PrivacyManager([maxretries[|minlength[|options]]]): If no Caller*ID \n"
    00058   "is sent, PrivacyManager answers the channel and asks the caller to\n"
    00059   "enter their phone number. The caller is given 3 attempts to do so.\n"
    00060   "The application does nothing if Caller*ID was received on the channel.\n"
    00061   "  Configuration file privacy.conf contains two variables:\n"
    00062   "   maxretries  default 3  -maximum number of attempts the caller is allowed \n"
    00063   "               to input a callerid.\n"
    00064   "   minlength   default 10 -minimum allowable digits in the input callerid number.\n"
    00065   "If you don't want to use the config file and have an i/o operation with\n"
    00066   "every call, you can also specify maxretries and minlength as application\n"
    00067   "parameters. Doing so supercedes any values set in privacy.conf.\n"
    00068   "The option string may contain the following character: \n"
    00069   "  'j' -- jump to n+101 priority after <maxretries> failed attempts to collect\n"
    00070   "         the minlength number of digits.\n"
    00071   "The application sets the following channel variable upon completion: \n"
    00072   "PRIVACYMGRSTATUS  The status of the privacy manager's attempt to collect \n"
    00073   "                  a phone number from the user. A text string that is either:\n"
    00074   "          SUCCESS | FAILED \n"
    00075 ;
    00076
    00077 STANDARD_LOCAL_USER;
    00078
    00079 LOCAL_USER_DECL;
    00080
    00081
    00082
    00083 static int privacy_exec (struct ast_channel *chan, void *data)
    00084 {
    00085    int res=0;
    00086    int retries;
    00087    int maxretries = 3;
    00088    int minlength = 10;
    00089    int x = 0;
    00090    char *s;
    00091    char phone[30];
    00092    struct localuser *u;
    00093    struct ast_config *cfg = NULL;
    00094    char *parse = NULL;
    00095    int priority_jump = 0;
    00096    AST_DECLARE_APP_ARGS(args,
    00097       AST_APP_ARG(maxretries);
    00098       AST_APP_ARG(minlength);
    00099       AST_APP_ARG(options);
    00100    );
    00101
    00102    LOCAL_USER_ADD (u);
    00103    if (!ast_strlen_zero(chan->cid.cid_num)) {
    00104       if (option_verbose > 2)
    00105          ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
    00106    } else {
    00107       /*Answer the channel if it is not already*/
    00108       if (chan->_state != AST_STATE_UP) {
    00109          res = ast_answer(chan);
    00110          if (res) {
    00111             LOCAL_USER_REMOVE(u);
    00112             return -1;
    00113          }
    00114       }
    00115
    00116       if (!ast_strlen_zero((char *)data))
    00117       {
    00118          parse = ast_strdupa(data);
    00119          if (!parse) {
    00120             ast_log(LOG_ERROR, "Out of memory!\n");
    00121             LOCAL_USER_REMOVE(u);
    00122             return -1;
    00123          }
    00124
    00125          AST_STANDARD_APP_ARGS(args, parse);
    00126
    00127          if (args.maxretries) {
    00128             if (sscanf(args.maxretries, "%30d", &x) == 1)
    00129                maxretries = x;
    00130             else
    00131                ast_log(LOG_WARNING, "Invalid max retries argument\n");
    00132          }
    00133          if (args.minlength) {
    00134             if (sscanf(args.minlength, "%30d", &x) == 1)
    00135                minlength = x;
    00136             else
    00137                ast_log(LOG_WARNING, "Invalid min length argument\n");
    00138          }
    00139          if (args.options)
    00140             if (strchr(args.options, 'j'))
    00141                priority_jump = 1;
    00142
    00143       }
    00144
    00145       if (!x)
    00146       {
    00147          /*Read in the config file*/
    00148          cfg = ast_config_load(PRIV_CONFIG);
    00149
    00150          if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
    00151             if (sscanf(s, "%30d", &x) == 1)
    00152                maxretries = x;
    00153             else
    00154                ast_log(LOG_WARNING, "Invalid max retries argument\n");
    00155             }
    00156
    00157          if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
    00158             if (sscanf(s, "%30d", &x) == 1)
    00159                minlength = x;
    00160             else
    00161                ast_log(LOG_WARNING, "Invalid min length argument\n");
    00162          }
    00163       }
    00164
    00165       /*Play unidentified call*/
    00166       res = ast_safe_sleep(chan, 1000);
    00167       if (!res)
    00168          res = ast_streamfile(chan, "privacy-unident", chan->language);
    00169       if (!res)
    00170          res = ast_waitstream(chan, "");
    00171
    00172       /*Ask for 10 digit number, give 3 attempts*/
    00173       for (retries = 0; retries < maxretries; retries++) {
    00174          if (!res)
    00175             res = ast_streamfile(chan, "privacy-prompt", chan->language);
    00176          if (!res)
    00177             res = ast_waitstream(chan, "");
    00178
    00179          if (!res )
    00180             res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
    00181
    00182          if (res < 0)
    00183             break;
    00184
    00185          /*Make sure we get at least digits*/
    00186          if (strlen(phone) >= minlength )
    00187             break;
    00188          else {
    00189             res = ast_streamfile(chan, "privacy-incorrect", chan->language);
    00190             if (!res)
    00191                res = ast_waitstream(chan, "");
    00192          }
    00193       }
    00194
    00195       /*Got a number, play sounds and send them on their way*/
    00196       if ((retries < maxretries) && res >= 0 ) {
    00197          res = ast_streamfile(chan, "privacy-thankyou", chan->language);
    00198          if (!res)
    00199             res = ast_waitstream(chan, "");
    00200
    00201          ast_set_callerid (chan, phone, "Privacy Manager", NULL);
    00202
    00203          /* Clear the unavailable presence bit so if it came in on PRI
    00204           * the caller id will now be passed out to other channels
    00205           */
    00206          chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
    00207
    00208          if (option_verbose > 2) {
    00209             ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
    00210          }
    00211          pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
    00212       } else {
    00213          if (priority_jump || option_priority_jumping)
    00214             ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
    00215          pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
    00216       }
    00217       if (cfg)
    00218          ast_config_destroy(cfg);
    00219    }
    00220
    00221   LOCAL_USER_REMOVE (u);
    00222   return 0;
    00223 }
    00224
    00225 int
    00226 unload_module (void)
    00227 {
    00228    int res;
    00229
    00230    res = ast_unregister_application (app);
    00231
    00232    STANDARD_HANGUP_LOCALUSERS;
    00233
    00234    return res;
    00235 }
    00236
    00237 int
    00238 load_module (void)
    00239 {
    00240   return ast_register_application (app, privacy_exec, synopsis,
    00241                descrip);
    00242 }
    00243
    00244 char *
    00245 description (void)
    00246 {
    00247   return tdesc;
    00248 }
    00249
    00250 int
    00251 usecount (void)
    00252 {
    00253   int res;
    00254   STANDARD_USECOUNT (res);
    00255   return res;
    00256 }
    00257
    00258 char *
    00259 key ()
    00260 {
    00261   return ASTERISK_GPL_KEY;
    00262 }