DETECT_DEADLOCKS can't be enabled without DEBUG_THREADS or it does nothing
[asterisk-bristuff.git] / apps / app_privacy.c
blob5da93eb401a19589475ca2a7fe4f54ae05b97f40
1 /*
2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
19 /*! \file
21 * \brief Block all calls without Caller*ID, require phone # to be entered
23 * \author Mark Spencer <markster@digium.com>
25 * \ingroup applications
28 #include "asterisk.h"
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
36 #include "asterisk/lock.h"
37 #include "asterisk/file.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/options.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/module.h"
44 #include "asterisk/translate.h"
45 #include "asterisk/image.h"
46 #include "asterisk/callerid.h"
47 #include "asterisk/app.h"
48 #include "asterisk/config.h"
50 #define PRIV_CONFIG "privacy.conf"
52 static char *app = "PrivacyManager";
54 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
56 static char *descrip =
57 " PrivacyManager([maxretries[|minlength[|options]]]): If no Caller*ID \n"
58 "is sent, PrivacyManager answers the channel and asks the caller to\n"
59 "enter their phone number. The caller is given 3 attempts to do so.\n"
60 "The application does nothing if Caller*ID was received on the channel.\n"
61 " Configuration file privacy.conf contains two variables:\n"
62 " maxretries default 3 -maximum number of attempts the caller is allowed \n"
63 " to input a callerid.\n"
64 " minlength default 10 -minimum allowable digits in the input callerid number.\n"
65 "If you don't want to use the config file and have an i/o operation with\n"
66 "every call, you can also specify maxretries and minlength as application\n"
67 "parameters. Doing so supercedes any values set in privacy.conf.\n"
68 "The option string may contain the following character: \n"
69 " 'j' -- jump to n+101 priority after <maxretries> failed attempts to collect\n"
70 " the minlength number of digits.\n"
71 "The application sets the following channel variable upon completion: \n"
72 "PRIVACYMGRSTATUS The status of the privacy manager's attempt to collect \n"
73 " a phone number from the user. A text string that is either:\n"
74 " SUCCESS | FAILED \n"
78 static int privacy_exec (struct ast_channel *chan, void *data)
80 int res=0;
81 int retries;
82 int maxretries = 3;
83 int minlength = 10;
84 int x = 0;
85 const char *s;
86 char phone[30];
87 struct ast_module_user *u;
88 struct ast_config *cfg = NULL;
89 char *parse = NULL;
90 int priority_jump = 0;
91 AST_DECLARE_APP_ARGS(args,
92 AST_APP_ARG(maxretries);
93 AST_APP_ARG(minlength);
94 AST_APP_ARG(options);
97 u = ast_module_user_add(chan);
99 if (!ast_strlen_zero(chan->cid.cid_num)) {
100 if (option_verbose > 2)
101 ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
102 } else {
103 /*Answer the channel if it is not already*/
104 if (chan->_state != AST_STATE_UP) {
105 res = ast_answer(chan);
106 if (res) {
107 ast_module_user_remove(u);
108 return -1;
112 if (!ast_strlen_zero(data)) {
113 parse = ast_strdupa(data);
115 AST_STANDARD_APP_ARGS(args, parse);
117 if (args.maxretries) {
118 if (sscanf(args.maxretries, "%d", &x) == 1)
119 maxretries = x;
120 else
121 ast_log(LOG_WARNING, "Invalid max retries argument\n");
123 if (args.minlength) {
124 if (sscanf(args.minlength, "%d", &x) == 1)
125 minlength = x;
126 else
127 ast_log(LOG_WARNING, "Invalid min length argument\n");
129 if (args.options)
130 if (strchr(args.options, 'j'))
131 priority_jump = 1;
135 if (!x)
137 /*Read in the config file*/
138 cfg = ast_config_load(PRIV_CONFIG);
140 if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
141 if (sscanf(s, "%d", &x) == 1)
142 maxretries = x;
143 else
144 ast_log(LOG_WARNING, "Invalid max retries argument\n");
147 if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
148 if (sscanf(s, "%d", &x) == 1)
149 minlength = x;
150 else
151 ast_log(LOG_WARNING, "Invalid min length argument\n");
155 /*Play unidentified call*/
156 res = ast_safe_sleep(chan, 1000);
157 if (!res)
158 res = ast_streamfile(chan, "privacy-unident", chan->language);
159 if (!res)
160 res = ast_waitstream(chan, "");
162 /*Ask for 10 digit number, give 3 attempts*/
163 for (retries = 0; retries < maxretries; retries++) {
164 if (!res)
165 res = ast_streamfile(chan, "privacy-prompt", chan->language);
166 if (!res)
167 res = ast_waitstream(chan, "");
169 if (!res )
170 res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
172 if (res < 0)
173 break;
175 /*Make sure we get at least digits*/
176 if (strlen(phone) >= minlength )
177 break;
178 else {
179 res = ast_streamfile(chan, "privacy-incorrect", chan->language);
180 if (!res)
181 res = ast_waitstream(chan, "");
185 /*Got a number, play sounds and send them on their way*/
186 if ((retries < maxretries) && res >= 0 ) {
187 res = ast_streamfile(chan, "privacy-thankyou", chan->language);
188 if (!res)
189 res = ast_waitstream(chan, "");
191 ast_set_callerid (chan, phone, "Privacy Manager", NULL);
193 /* Clear the unavailable presence bit so if it came in on PRI
194 * the caller id will now be passed out to other channels
196 chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
198 if (option_verbose > 2) {
199 ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
201 pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
202 } else {
203 if (priority_jump || ast_opt_priority_jumping)
204 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
205 pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
207 if (cfg)
208 ast_config_destroy(cfg);
211 ast_module_user_remove(u);
213 return 0;
216 static int unload_module(void)
218 int res;
220 res = ast_unregister_application (app);
222 ast_module_user_hangup_all();
224 return res;
227 static int load_module(void)
229 return ast_register_application (app, privacy_exec, synopsis, descrip);
232 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");