8cfbd88f318e3474826bb21d6cba813b0b832353
[asterisk/asterisk.git] / apps / app_privacy.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Block all calls without Caller*ID, require phone # to be entered
5  * 
6  * Copyright (C) 1999-2004, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/options.h>
18 #include <asterisk/channel.h>
19 #include <asterisk/pbx.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/image.h>
23 #include <asterisk/callerid.h>
24 #include <asterisk/app.h>
25 #include <asterisk/config.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #define PRIV_CONFIG "privacy.conf"
30
31 static char *tdesc = "Require phone number to be entered, if no CallerID sent";
32
33 static char *app = "PrivacyManager";
34
35 static char *synopsis = "Require phone number to be entered, if no CallerID sent";
36
37 static char *descrip =
38   "  PrivacyManager: If no Caller*ID is sent, PrivacyManager answers the\n"
39   "channel and asks the caller to enter their phone number.\n"
40   "The caller is given 3 attempts.  If after 3 attempts, they do not enter\n"
41   "at least a 10 digit phone number, and if there exists a priority n + 101,\n"
42   "where 'n' is the priority of the current instance, then  the\n"
43   "channel  will  be  setup  to continue at that priority level.\n"
44   "Otherwise, it returns 0.  Does nothing if Caller*ID was received on the\n"
45   "channel.\n"
46   "  Configuration file privacy.conf contains two variables:\n"
47   "   maxretries  default 3  -maximum number of attempts the caller is allowed to input a callerid.\n"
48   "   minlength   default 10 -minimum allowable digits in the input callerid number.\n"
49 ;
50
51 STANDARD_LOCAL_USER;
52
53 LOCAL_USER_DECL;
54
55
56
57 static int
58 privacy_exec (struct ast_channel *chan, void *data)
59 {
60         int res=0;
61         int retries;
62         int maxretries = 3;
63         int minlength = 10;
64         int x;
65         char *s;
66         char phone[30];
67         char new_cid[144];
68         struct localuser *u;
69         struct ast_config *cfg;
70
71         LOCAL_USER_ADD (u);
72         if (chan->cid.cid_num)
73         {
74                 if (option_verbose > 2)
75                         ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
76         }
77         else
78         {
79                 /*Answer the channel if it is not already*/
80                 if (chan->_state != AST_STATE_UP) {
81                         res = ast_answer(chan);
82                         if (res) {
83                                 LOCAL_USER_REMOVE(u);
84                                 return -1;
85                         }
86                 }
87                 /*Read in the config file*/
88                 cfg = ast_load(PRIV_CONFIG);
89                 
90                 
91                 /*Play unidentified call*/
92                 res = ast_safe_sleep(chan, 1000);
93                 if (!res)
94                         res = ast_streamfile(chan, "privacy-unident", chan->language);
95                 if (!res)
96                         res = ast_waitstream(chan, "");
97
98         if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
99                 if (sscanf(s, "%d", &x) == 1) {
100                         maxretries = x;
101                 } else {
102                         ast_log(LOG_WARNING, "Invalid max retries argument\n");
103                 }
104         }
105         if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
106                 if (sscanf(s, "%d", &x) == 1) {
107                         minlength = x;
108                 } else {
109                         ast_log(LOG_WARNING, "Invalid min length argument\n");
110                 }
111         }
112                         
113                 /*Ask for 10 digit number, give 3 attempts*/
114                 for (retries = 0; retries < maxretries; retries++) {
115                         if (!res)
116                                 res = ast_streamfile(chan, "privacy-prompt", chan->language);
117                         if (!res)
118                                 res = ast_waitstream(chan, "");
119
120                         if (!res ) 
121                                 res = ast_readstring(chan, phone, sizeof(phone) - 1, /* digit timeout ms */ 3200, /* first digit timeout */ 5000, "#");
122
123                         if (res < 0)
124                                 break;
125
126                         /*Make sure we get at least digits*/
127                         if (strlen(phone) >= minlength ) 
128                                 break;
129                         else {
130                                 res = ast_streamfile(chan, "privacy-incorrect", chan->language);
131                                 if (!res)
132                                         res = ast_waitstream(chan, "");
133                         }
134                 }
135                 
136                 /*Got a number, play sounds and send them on their way*/
137                 if ((retries < maxretries) && res == 1 ) {
138                         res = ast_streamfile(chan, "privacy-thankyou", chan->language);
139                         if (!res)
140                                 res = ast_waitstream(chan, "");
141                         ast_set_callerid (chan, phone, "Privacy Manager", NULL);
142                         if (option_verbose > 2)
143                                 ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",new_cid);
144                 } else {
145                         /*Send the call to n+101 priority, where n is the current priority*/
146                         if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
147                                 chan->priority+=100;
148                 }
149                 if (cfg) 
150                         ast_destroy(cfg);
151         }
152
153   LOCAL_USER_REMOVE (u);
154   return 0;
155 }
156
157 int
158 unload_module (void)
159 {
160   STANDARD_HANGUP_LOCALUSERS;
161   return ast_unregister_application (app);
162 }
163
164 int
165 load_module (void)
166 {
167   return ast_register_application (app, privacy_exec, synopsis,
168                                    descrip);
169 }
170
171 char *
172 description (void)
173 {
174   return tdesc;
175 }
176
177 int
178 usecount (void)
179 {
180   int res;
181   STANDARD_USECOUNT (res);
182   return res;
183 }
184
185 char *
186 key ()
187 {
188   return ASTERISK_GPL_KEY;
189 }