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