remove lots of useless checks of the result of ast_strdupa
[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 <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31
32 #include "asterisk.h"
33
34 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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 *tdesc = "Require phone number to be entered, if no CallerID sent";
53
54 static char *app = "PrivacyManager";
55
56 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
57
58 static char *descrip =
59   "  PrivacyManager([maxretries[|minlength[|options]]]): If no Caller*ID \n"
60   "is sent, PrivacyManager answers the channel and asks the caller to\n"
61   "enter their phone number. The caller is given 3 attempts to do so.\n"
62   "The application does nothing if Caller*ID was received on the channel.\n"
63   "  Configuration file privacy.conf contains two variables:\n"
64   "   maxretries  default 3  -maximum number of attempts the caller is allowed \n"
65   "               to input a callerid.\n"
66   "   minlength   default 10 -minimum allowable digits in the input callerid number.\n"
67   "If you don't want to use the config file and have an i/o operation with\n"
68   "every call, you can also specify maxretries and minlength as application\n"
69   "parameters. Doing so supercedes any values set in privacy.conf.\n"
70   "The option string may contain the following character: \n"
71   "  'j' -- jump to n+101 priority after <maxretries> failed attempts to collect\n"
72   "         the minlength number of digits.\n"
73   "The application sets the following channel variable upon completion: \n"
74   "PRIVACYMGRSTATUS  The status of the privacy manager's attempt to collect \n"
75   "                  a phone number from the user. A text string that is either:\n" 
76   "          SUCCESS | FAILED \n"
77 ;
78
79 STANDARD_LOCAL_USER;
80
81 LOCAL_USER_DECL;
82
83
84
85 static int privacy_exec (struct ast_channel *chan, void *data)
86 {
87         int res=0;
88         int retries;
89         int maxretries = 3;
90         int minlength = 10;
91         int x = 0;
92         char *s;
93         char phone[30];
94         struct localuser *u;
95         struct ast_config *cfg = NULL;
96         char *parse = NULL;
97         int priority_jump = 0;
98         AST_DECLARE_APP_ARGS(args,
99                 AST_APP_ARG(maxretries);
100                 AST_APP_ARG(minlength);
101                 AST_APP_ARG(options);
102         );
103
104         LOCAL_USER_ADD (u);
105         if (!ast_strlen_zero(chan->cid.cid_num)) {
106                 if (option_verbose > 2)
107                         ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
108         } else {
109                 /*Answer the channel if it is not already*/
110                 if (chan->_state != AST_STATE_UP) {
111                         res = ast_answer(chan);
112                         if (res) {
113                                 LOCAL_USER_REMOVE(u);
114                                 return -1;
115                         }
116                 }
117
118                 if (!ast_strlen_zero((char *)data))
119                 {
120                         parse = ast_strdupa(data);
121                         
122                         AST_STANDARD_APP_ARGS(args, parse);
123
124                         if (args.maxretries) {
125                                 if (sscanf(args.maxretries, "%d", &x) == 1)
126                                         maxretries = x;
127                                 else
128                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
129                         }
130                         if (args.minlength) {
131                                 if (sscanf(args.minlength, "%d", &x) == 1)
132                                         minlength = x;
133                                 else
134                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
135                         }
136                         if (args.options)
137                                 if (strchr(args.options, 'j'))
138                                         priority_jump = 1;
139
140                 }               
141
142                 if (!x)
143                 {
144                         /*Read in the config file*/
145                         cfg = ast_config_load(PRIV_CONFIG);
146                 
147                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
148                                 if (sscanf(s, "%d", &x) == 1) 
149                                         maxretries = x;
150                                 else
151                                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
152                         }
153
154                         if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
155                                 if (sscanf(s, "%d", &x) == 1) 
156                                         minlength = x;
157                                 else
158                                         ast_log(LOG_WARNING, "Invalid min length argument\n");
159                         }
160                 }       
161                 
162                 /*Play unidentified call*/
163                 res = ast_safe_sleep(chan, 1000);
164                 if (!res)
165                         res = ast_streamfile(chan, "privacy-unident", chan->language);
166                 if (!res)
167                         res = ast_waitstream(chan, "");
168
169                 /*Ask for 10 digit number, give 3 attempts*/
170                 for (retries = 0; retries < maxretries; retries++) {
171                         if (!res)
172                                 res = ast_streamfile(chan, "privacy-prompt", chan->language);
173                         if (!res)
174                                 res = ast_waitstream(chan, "");
175
176                         if (!res ) 
177                                 res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
178
179                         if (res < 0)
180                                 break;
181
182                         /*Make sure we get at least digits*/
183                         if (strlen(phone) >= minlength ) 
184                                 break;
185                         else {
186                                 res = ast_streamfile(chan, "privacy-incorrect", chan->language);
187                                 if (!res)
188                                         res = ast_waitstream(chan, "");
189                         }
190                 }
191                 
192                 /*Got a number, play sounds and send them on their way*/
193                 if ((retries < maxretries) && !res ) {
194                         res = ast_streamfile(chan, "privacy-thankyou", chan->language);
195                         if (!res)
196                                 res = ast_waitstream(chan, "");
197                         ast_set_callerid (chan, phone, "Privacy Manager", NULL);
198                         if (option_verbose > 2)
199                                 ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone);
200                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
201                 } else {
202                         if (priority_jump || ast_opt_priority_jumping)  
203                                 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
204                         pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
205                 }
206                 if (cfg) 
207                         ast_config_destroy(cfg);
208         }
209
210   LOCAL_USER_REMOVE (u);
211   return 0;
212 }
213
214 int
215 unload_module (void)
216 {
217         int res;
218
219         res = ast_unregister_application (app);
220
221         STANDARD_HANGUP_LOCALUSERS;
222
223         return res;
224 }
225
226 int
227 load_module (void)
228 {
229   return ast_register_application (app, privacy_exec, synopsis,
230                                    descrip);
231 }
232
233 char *
234 description (void)
235 {
236   return tdesc;
237 }
238
239 int
240 usecount (void)
241 {
242   int res;
243   STANDARD_USECOUNT (res);
244   return res;
245 }
246
247 char *
248 key ()
249 {
250   return ASTERISK_GPL_KEY;
251 }