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