Applications no longer need to call ast_module_user_add and ast_module_user_remove...
[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 <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35
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"
49
50 #define PRIV_CONFIG "privacy.conf"
51
52 static char *app = "PrivacyManager";
53
54 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
55
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 application sets the following channel variable upon completion: \n"
69   "PRIVACYMGRSTATUS  The status of the privacy manager's attempt to collect \n"
70   "                  a phone number from the user. A text string that is either:\n" 
71   "          SUCCESS | FAILED \n"
72 ;
73
74
75 static int privacy_exec (struct ast_channel *chan, void *data)
76 {
77         int res=0;
78         int retries;
79         int maxretries = 3;
80         int minlength = 10;
81         int x = 0;
82         const char *s;
83         char phone[30];
84         struct ast_config *cfg = NULL;
85         char *parse = NULL;
86         AST_DECLARE_APP_ARGS(args,
87                 AST_APP_ARG(maxretries);
88                 AST_APP_ARG(minlength);
89                 AST_APP_ARG(options);
90         );
91
92         if (!ast_strlen_zero(chan->cid.cid_num)) {
93                 if (option_verbose > 2)
94                         ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
95         } else {
96                 /*Answer the channel if it is not already*/
97                 if (chan->_state != AST_STATE_UP) {
98                         if ((res = ast_answer(chan)))
99                                 return -1;
100                 }
101
102                 if (!ast_strlen_zero(data)) {
103                         parse = ast_strdupa(data);
104                         
105                         AST_STANDARD_APP_ARGS(args, parse);
106
107                         if (args.maxretries) {
108                                 if (sscanf(args.maxretries, "%d", &x) == 1)
109                                         maxretries = x;
110                                 else
111                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
112                         }
113                         if (args.minlength) {
114                                 if (sscanf(args.minlength, "%d", &x) == 1)
115                                         minlength = x;
116                                 else
117                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
118                         }
119
120                 }               
121
122                 if (!x)
123                 {
124                         /*Read in the config file*/
125                         cfg = ast_config_load(PRIV_CONFIG);
126                 
127                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
128                                 if (sscanf(s, "%d", &x) == 1) 
129                                         maxretries = x;
130                                 else
131                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
132                         }
133
134                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
135                                 if (sscanf(s, "%d", &x) == 1) 
136                                         minlength = x;
137                                 else
138                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
139                         }
140                 }       
141                 
142                 /*Play unidentified call*/
143                 res = ast_safe_sleep(chan, 1000);
144                 if (!res)
145                         res = ast_streamfile(chan, "privacy-unident", chan->language);
146                 if (!res)
147                         res = ast_waitstream(chan, "");
148
149                 /*Ask for 10 digit number, give 3 attempts*/
150                 for (retries = 0; retries < maxretries; retries++) {
151                         if (!res)
152                                 res = ast_streamfile(chan, "privacy-prompt", chan->language);
153                         if (!res)
154                                 res = ast_waitstream(chan, "");
155
156                         if (!res ) 
157                                 res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
158
159                         if (res < 0)
160                                 break;
161
162                         /*Make sure we get at least digits*/
163                         if (strlen(phone) >= minlength ) 
164                                 break;
165                         else {
166                                 res = ast_streamfile(chan, "privacy-incorrect", chan->language);
167                                 if (!res)
168                                         res = ast_waitstream(chan, "");
169                         }
170                 }
171                 
172                 /*Got a number, play sounds and send them on their way*/
173                 if ((retries < maxretries) && res >= 0 ) {
174                         res = ast_streamfile(chan, "privacy-thankyou", chan->language);
175                         if (!res)
176                                 res = ast_waitstream(chan, "");
177
178                         ast_set_callerid (chan, phone, "Privacy Manager", NULL); 
179
180                         /* Clear the unavailable presence bit so if it came in on PRI
181                          * the caller id will now be passed out to other channels
182                          */
183                         chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
184
185                         if (option_verbose > 2) {
186                                 ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
187                         }
188                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
189                 } else {
190                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
191                 }
192                 if (cfg) 
193                         ast_config_destroy(cfg);
194         }
195
196         return 0;
197 }
198
199 static int unload_module(void)
200 {
201         return ast_unregister_application (app);
202 }
203
204 static int load_module(void)
205 {
206         return ast_register_application(app, privacy_exec, synopsis, descrip);
207 }
208
209 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");