remove another set of redundant #include "asterisk/options.h"
[asterisk/asterisk.git] / apps / app_privacy.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
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.
13  *
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.
17  */
18
19 /*! \file
20  *
21  * \brief Block all calls without Caller*ID, require phone # to be entered
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * 
25  * \ingroup applications
26  */
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include "asterisk/lock.h"
33 #include "asterisk/file.h"
34 #include "asterisk/utils.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/module.h"
38 #include "asterisk/translate.h"
39 #include "asterisk/image.h"
40 #include "asterisk/callerid.h"
41 #include "asterisk/app.h"
42 #include "asterisk/config.h"
43
44 #define PRIV_CONFIG "privacy.conf"
45
46 static char *app = "PrivacyManager";
47
48 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
49
50 static char *descrip =
51   "  PrivacyManager([maxretries[,minlength[,options]]]): If no Caller*ID \n"
52   "is sent, PrivacyManager answers the channel and asks the caller to\n"
53   "enter their phone number. The caller is given 3 attempts to do so.\n"
54   "The application does nothing if Caller*ID was received on the channel.\n"
55   "  Configuration file privacy.conf contains two variables:\n"
56   "   maxretries  default 3  -maximum number of attempts the caller is allowed \n"
57   "               to input a callerid.\n"
58   "   minlength   default 10 -minimum allowable digits in the input callerid number.\n"
59   "If you don't want to use the config file and have an i/o operation with\n"
60   "every call, you can also specify maxretries and minlength as application\n"
61   "parameters. Doing so supercedes any values set in privacy.conf.\n"
62   "The application sets the following channel variable upon completion: \n"
63   "PRIVACYMGRSTATUS  The status of the privacy manager's attempt to collect \n"
64   "                  a phone number from the user. A text string that is either:\n" 
65   "          SUCCESS | FAILED \n"
66 ;
67
68
69 static int privacy_exec (struct ast_channel *chan, void *data)
70 {
71         int res=0;
72         int retries;
73         int maxretries = 3;
74         int minlength = 10;
75         int x = 0;
76         const char *s;
77         char phone[30];
78         struct ast_config *cfg = NULL;
79         char *parse = NULL;
80         struct ast_flags config_flags = { 0 };
81         AST_DECLARE_APP_ARGS(args,
82                 AST_APP_ARG(maxretries);
83                 AST_APP_ARG(minlength);
84                 AST_APP_ARG(options);
85         );
86
87         if (!ast_strlen_zero(chan->cid.cid_num)) {
88                 if (option_verbose > 2)
89                         ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
90         } else {
91                 /*Answer the channel if it is not already*/
92                 if (chan->_state != AST_STATE_UP) {
93                         if ((res = ast_answer(chan)))
94                                 return -1;
95                 }
96
97                 if (!ast_strlen_zero(data)) {
98                         parse = ast_strdupa(data);
99                         
100                         AST_STANDARD_APP_ARGS(args, parse);
101
102                         if (args.maxretries) {
103                                 if (sscanf(args.maxretries, "%d", &x) == 1)
104                                         maxretries = x;
105                                 else
106                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
107                         }
108                         if (args.minlength) {
109                                 if (sscanf(args.minlength, "%d", &x) == 1)
110                                         minlength = x;
111                                 else
112                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
113                         }
114
115                 }               
116
117                 if (!x)
118                 {
119                         /*Read in the config file*/
120                         cfg = ast_config_load(PRIV_CONFIG, config_flags);
121                 
122                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
123                                 if (sscanf(s, "%d", &x) == 1) 
124                                         maxretries = x;
125                                 else
126                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
127                         }
128
129                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
130                                 if (sscanf(s, "%d", &x) == 1) 
131                                         minlength = x;
132                                 else
133                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
134                         }
135                 }       
136                 
137                 /*Play unidentified call*/
138                 res = ast_safe_sleep(chan, 1000);
139                 if (!res)
140                         res = ast_streamfile(chan, "privacy-unident", chan->language);
141                 if (!res)
142                         res = ast_waitstream(chan, "");
143
144                 /*Ask for 10 digit number, give 3 attempts*/
145                 for (retries = 0; retries < maxretries; retries++) {
146                         if (!res)
147                                 res = ast_streamfile(chan, "privacy-prompt", chan->language);
148                         if (!res)
149                                 res = ast_waitstream(chan, "");
150
151                         if (!res ) 
152                                 res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
153
154                         if (res < 0)
155                                 break;
156
157                         /*Make sure we get at least digits*/
158                         if (strlen(phone) >= minlength ) 
159                                 break;
160                         else {
161                                 res = ast_streamfile(chan, "privacy-incorrect", chan->language);
162                                 if (!res)
163                                         res = ast_waitstream(chan, "");
164                         }
165                 }
166                 
167                 /*Got a number, play sounds and send them on their way*/
168                 if ((retries < maxretries) && res >= 0 ) {
169                         res = ast_streamfile(chan, "privacy-thankyou", chan->language);
170                         if (!res)
171                                 res = ast_waitstream(chan, "");
172
173                         ast_set_callerid (chan, phone, "Privacy Manager", NULL); 
174
175                         /* Clear the unavailable presence bit so if it came in on PRI
176                          * the caller id will now be passed out to other channels
177                          */
178                         chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
179
180                         if (option_verbose > 2) {
181                                 ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
182                         }
183                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
184                 } else {
185                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
186                 }
187                 if (cfg) 
188                         ast_config_destroy(cfg);
189         }
190
191         return 0;
192 }
193
194 static int unload_module(void)
195 {
196         return ast_unregister_application (app);
197 }
198
199 static int load_module(void)
200 {
201         return ast_register_application(app, privacy_exec, synopsis, descrip);
202 }
203
204 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");