Fix searching for non-default mailboxes
[asterisk/asterisk.git] / app.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Channel Management
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <pthread.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <signal.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <dirent.h>
23 #include <asterisk/channel.h>
24 #include <asterisk/file.h>
25 #include <asterisk/app.h>
26 #include <asterisk/dsp.h>
27 #include <asterisk/logger.h>
28 #include <asterisk/options.h>
29 #include "asterisk.h"
30 #include "astconf.h"
31
32 /* set timeout to 0 for "standard" timeouts. Set timeout to -1 for 
33    "ludicrous time" (essentially never times out) */
34 int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
35 {
36         int res,to,fto;
37         /* XXX Merge with full version? XXX */
38         if (prompt) {
39                 res = ast_streamfile(c, prompt, c->language);
40                 if (res < 0)
41                         return res;
42         }
43         fto = 6000;
44         to = 2000;
45         if (timeout > 0) fto = to = timeout;
46         if (timeout < 0) fto = to = 1000000000;
47         res = ast_readstring(c, s, maxlen, to, fto, "#");
48         return res;
49 }
50
51
52 int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
53 {
54         int res,to,fto;
55         if (prompt) {
56                 res = ast_streamfile(c, prompt, c->language);
57                 if (res < 0)
58                         return res;
59         }
60         fto = 6000;
61         to = 2000;
62         if (timeout > 0) fto = to = timeout;
63         if (timeout < 0) fto = to = 1000000000;
64         res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
65         return res;
66 }
67
68 int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prompt, int silence, int maxsec)
69 {
70         int res;
71         struct ast_filestream *writer;
72         int rfmt;
73         int totalms=0, total;
74         
75         struct ast_frame *f;
76         struct ast_dsp *sildet;
77         /* Play prompt if requested */
78         if (prompt) {
79                 res = ast_streamfile(c, prompt, c->language);
80                 if (res < 0)
81                         return res;
82                 res = ast_waitstream(c,"");
83                 if (res < 0)
84                         return res;
85         }
86         rfmt = c->readformat;
87         res = ast_set_read_format(c, AST_FORMAT_SLINEAR);
88         if (res < 0) {
89                 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
90                 return -1;
91         }
92         sildet = ast_dsp_new();
93         if (!sildet) {
94                 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
95                 return -1;
96         }
97         writer = ast_writefile(dest, dstfmt, "Voice file", 0, 0, 0666);
98         if (!writer) {
99                 ast_log(LOG_WARNING, "Unable to open file '%s' in format '%s' for writing\n", dest, dstfmt);
100                 ast_dsp_free(sildet);
101                 return -1;
102         }
103         for(;;) {
104                 if ((res = ast_waitfor(c, 2000)) < 0) {
105                         ast_log(LOG_NOTICE, "Waitfor failed while recording file '%s' format '%s'\n", dest, dstfmt);
106                         break;
107                 }
108                 if (res) {
109                         f = ast_read(c);
110                         if (!f) {
111                                 ast_log(LOG_NOTICE, "Hungup while recording file '%s' format '%s'\n", dest, dstfmt);
112                                 break;
113                         }
114                         if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
115                                 /* Ended happily with DTMF */
116                                 ast_frfree(f);
117                                 break;
118                         } else if (f->frametype == AST_FRAME_VOICE) {
119                                 ast_dsp_silence(sildet, f, &total); 
120                                 if (total > silence) {
121                                         /* Ended happily with silence */
122                                         ast_frfree(f);
123                                         break;
124                                 }
125                                 totalms += f->samples / 8;
126                                 if (totalms > maxsec * 1000) {
127                                         /* Ended happily with too much stuff */
128                                         ast_log(LOG_NOTICE, "Constraining voice on '%s' to %d seconds\n", c->name, maxsec);
129                                         ast_frfree(f);
130                                         break;
131                                 }
132                         }
133                         ast_frfree(f);
134                 }
135         }
136         res = ast_set_read_format(c, rfmt);
137         if (res)
138                 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", c->name);
139         ast_dsp_free(sildet);
140         ast_closestream(writer);
141         return 0;
142 }
143
144 int ast_app_has_voicemail(const char *mailbox)
145 {
146         DIR *dir;
147         struct dirent *de;
148         char fn[256];
149         char tmp[256]="";
150         char *mb, *cur;
151         char *context;
152         int ret;
153         /* If no mailbox, return immediately */
154         if (!strlen(mailbox))
155                 return 0;
156         if (strchr(mailbox, ',')) {
157                 strncpy(tmp, mailbox, sizeof(tmp));
158                 mb = tmp;
159                 ret = 0;
160                 while((cur = strsep(&mb, ","))) {
161                         if (strlen(cur)) {
162                                 if (ast_app_has_voicemail(cur))
163                                         return 1; 
164                         }
165                 }
166                 return 0;
167         }
168         strncpy(tmp, mailbox, sizeof(tmp) - 1);
169         context = strchr(tmp, '@');
170         if (context) {
171                 *context = '\0';
172                 context++;
173         } else
174                 context = "default";
175         snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
176         dir = opendir(fn);
177         if (!dir)
178                 return 0;
179         while ((de = readdir(dir))) {
180                 if (!strncasecmp(de->d_name, "msg", 3))
181                         break;
182         }
183         closedir(dir);
184         if (de)
185                 return 1;
186         return 0;
187 }
188
189 int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
190 {
191         DIR *dir;
192         struct dirent *de;
193         char fn[256];
194         char tmp[256]="";
195         char *mb, *cur;
196         char *context;
197         int ret;
198         if (newmsgs)
199                 *newmsgs = 0;
200         if (oldmsgs)
201                 *oldmsgs = 0;
202         /* If no mailbox, return immediately */
203         if (!strlen(mailbox))
204                 return 0;
205         if (strchr(mailbox, ',')) {
206                 int tmpnew, tmpold;
207                 strncpy(tmp, mailbox, sizeof(tmp));
208                 mb = tmp;
209                 ret = 0;
210                 while((cur = strsep(&mb, ", "))) {
211                         if (strlen(cur)) {
212                                 if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
213                                         return -1;
214                                 else {
215                                         if (newmsgs)
216                                                 *newmsgs += tmpnew; 
217                                         if (oldmsgs)
218                                                 *oldmsgs += tmpold;
219                                 }
220                         }
221                 }
222                 return 0;
223         }
224         strncpy(tmp, mailbox, sizeof(tmp) - 1);
225         context = strchr(tmp, '@');
226         if (context) {
227                 *context = '\0';
228                 context++;
229         } else
230                 context = "default";
231         if (newmsgs) {
232                 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
233                 dir = opendir(fn);
234                 if (dir) {
235                         while ((de = readdir(dir))) {
236                                 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
237                                         !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
238                                                 (*newmsgs)++;
239                                         
240                         }
241                         closedir(dir);
242                 }
243         }
244         if (oldmsgs) {
245                 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
246                 dir = opendir(fn);
247                 if (dir) {
248                         while ((de = readdir(dir))) {
249                                 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
250                                         !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
251                                                 (*oldmsgs)++;
252                                         
253                         }
254                         closedir(dir);
255                 }
256         }
257         return 0;
258 }