Use find_user for existsmailbox
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Trivial application to dial a channel and send an URL on answer
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 <asterisk/lock.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/options.h>
20 #include <asterisk/module.h>
21 #include <asterisk/translate.h>
22 #include <asterisk/say.h>
23 #include <asterisk/config.h>
24 #include <asterisk/parking.h>
25 #include <asterisk/musiconhold.h>
26 #include <asterisk/callerid.h>
27 #include <asterisk/utils.h>
28 #include <asterisk/app.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <sys/time.h>
36 #include <sys/signal.h>
37 #include <netinet/in.h>
38
39 #include <pthread.h>
40
41 static char *tdesc = "Dialing Application";
42
43 static char *app = "Dial";
44
45 static char *synopsis = "Place a call and connect to the current channel";
46
47 static char *descrip =
48 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
49 "Requests one or more channels and places specified outgoing calls on them.\n"
50 "As soon as a channel answers, the Dial app will answer the originating\n"
51 "channel (if it needs to be answered) and will bridge a call with the channel\n"
52 "which first answered. All other calls placed by the Dial app will be hung up\n"
53 "If a timeout is not specified, the Dial application will wait indefinitely\n"
54 "until either one of the called channels answers, the user hangs up, or all\n"
55 "channels return busy or error. In general, the dialer will return 0 if it\n"
56 "was unable to place the call, or the timeout expired. However, if all\n"
57 "channels were busy, and there exists an extension with priority n+101 (where\n"
58 "n is the priority of the dialer instance), then it will be the next\n"
59 "executed extension (this allows you to setup different behavior on busy from\n"
60 "no-answer).\n"
61 "  This application returns -1 if the originating channel hangs up, or if the\n"
62 "call is bridged and either of the parties in the bridge terminate the call.\n"
63 "The option string may contain zero or more of the following characters:\n"
64 "      't' -- allow the called user transfer the calling user by hitting #.\n"
65 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
66 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
67 "      'm' -- provide hold music to the calling party until answered.\n"
68 "      'H' -- allow caller to hang up by hitting *.\n"
69 "      'C' -- reset call detail record for this call.\n"
70 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
71 "      'g' -- goes on in context if the destination channel hangs up\n"
72 "      'A(x)' -- play an announcement to the called party, using x as file\n"
73 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
74 "      'D([digits])'  -- Send DTMF digit string *after* called party has answered\n"
75 "                        but before the bridge. (w=500ms sec pause)\n"
76 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left (repeated every 'z' ms)\n"
77 "                     -- Only 'x' is required, 'y' and 'z' are optional.\n"
78 "                     -- The following special variables are optional:\n"
79 "                       ** LIMIT_PLAYAUDIO_CALLER    (default yes) Play sounds to the caller.\n"
80 "                       ** LIMIT_PLAYAUDIO_CALLEE    Play sounds to the callee.\n"
81 "                       ** LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
82 "                       ** LIMIT_CONNECT_FILE        File to play when call begins.\n"
83 "                       ** LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
84 "                     -- 'timeleft' is a special sound macro to auto-say the time left and is the default.\n\n"
85 "  In addition to transferring the call, a call may be parked and then picked\n"
86 "up by another user.\n"
87 "  The optional URL will be sent to the called party if the channel supports\n"
88 "it.\n";
89
90 /* We define a customer "local user" structure because we
91    use it not only for keeping track of what is in use but
92    also for keeping track of who we're dialing. */
93
94 struct localuser {
95         struct ast_channel *chan;
96         int stillgoing;
97         int allowredirect_in;
98         int allowredirect_out;
99         int ringbackonly;
100         int musiconhold;
101         int allowdisconnect;
102         struct localuser *next;
103 };
104
105 LOCAL_USER_DECL;
106
107 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
108 {
109         /* Hang up a tree of stuff */
110         struct localuser *oo;
111         while(outgoing) {
112                 /* Hangup any existing lines we have open */
113                 if (outgoing->chan && (outgoing->chan != exception))
114                         ast_hangup(outgoing->chan);
115                 oo = outgoing;
116                 outgoing=outgoing->next;
117                 free(oo);
118         }
119 }
120
121 #define MAX 256
122
123 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect)
124 {
125         struct localuser *o;
126         int found;
127         int numlines;
128         int sentringing = 0;
129         int numbusies = 0;
130         int orig = *to;
131         struct ast_frame *f;
132         struct ast_channel *peer = NULL;
133         struct ast_channel *watchers[MAX];
134         int pos;
135         int single;
136         int moh=0;
137         int ringind=0;
138         struct ast_channel *winner;
139         
140         single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
141         
142         if (single) {
143                 /* Turn off hold music, etc */
144                 ast_indicate(in, -1);
145                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
146                 ast_channel_make_compatible(outgoing->chan, in);
147         }
148         
149         if (outgoing) {
150                 moh = outgoing->musiconhold;
151                 ringind = outgoing->ringbackonly;
152                 if (outgoing->musiconhold) {
153                         ast_moh_start(in, NULL);
154                 } else if (outgoing->ringbackonly) {
155                         ast_indicate(in, AST_CONTROL_RINGING);
156                         sentringing++;
157                 }
158         }
159         
160         while(*to && !peer) {
161                 o = outgoing;
162                 found = -1;
163                 pos = 1;
164                 numlines = 0;
165                 watchers[0] = in;
166                 while(o) {
167                         /* Keep track of important channels */
168                         if (o->stillgoing && o->chan) {
169                                 watchers[pos++] = o->chan;
170                                 found = 1;
171                         }
172                         o = o->next;
173                         numlines++;
174                 }
175                 if (found < 0) {
176                         if (numlines == numbusies) {
177                                 if (option_verbose > 2)
178                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
179                                 /* See if there is a special busy message */
180                                 if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) 
181                                         in->priority+=100;
182                         } else {
183                                 if (option_verbose > 2)
184                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
185                         }
186                         *to = 0;
187                         /* if no one available we'd better stop MOH/ringing to */
188                         if (moh) {
189                                 ast_moh_stop(in);
190                         } else if (sentringing) {
191                                 ast_indicate(in, -1);
192                         }
193                         return NULL;
194                 }
195                 winner = ast_waitfor_n(watchers, pos, to);
196                 o = outgoing;
197                 while(o) {
198                         if (o->stillgoing && o->chan && (o->chan->_state == AST_STATE_UP)) {
199                                 if (!peer) {
200                                         if (option_verbose > 2)
201                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
202                                         peer = o->chan;
203                                         *allowredir_in = o->allowredirect_in;
204                                         *allowredir_out = o->allowredirect_out;
205                                         *allowdisconnect = o->allowdisconnect;
206                                 }
207                         } else if (o->chan && (o->chan == winner)) {
208                                 if (!ast_strlen_zero(o->chan->call_forward)) {
209                                         char tmpchan[256];
210                                         /* Before processing channel, go ahead and check for forwarding */
211                                         if (option_verbose > 2)
212                                                 ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name);
213                                         /* Setup parameters */
214                                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
215                                         ast_hangup(o->chan);
216                                         o->chan = ast_request("Local", in->nativeformats, tmpchan);
217                                         if (!o->chan) {
218                                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
219                                                 o->stillgoing = 0;
220                                                 numbusies++;
221                                         } else {
222                                                 if (in->callerid) {
223                                                         if (o->chan->callerid)
224                                                                 free(o->chan->callerid);
225                                                         o->chan->callerid = malloc(strlen(in->callerid) + 1);
226                                                         if (o->chan->callerid)
227                                                                 strncpy(o->chan->callerid, in->callerid, strlen(in->callerid) + 1);
228                                                         else
229                                                                 ast_log(LOG_WARNING, "Out of memory\n");
230                                                 }
231                                                 if (in->ani) {
232                                                         if (o->chan->ani)
233                                                                 free(o->chan->ani);
234                                                         o->chan->ani = malloc(strlen(in->ani) + 1);
235                                                         if (o->chan->ani)
236                                                                 strncpy(o->chan->ani, in->ani, strlen(in->ani) + 1);
237                                                         else
238                                                                 ast_log(LOG_WARNING, "Out of memory\n");
239                                                 }
240                                                 if (o->chan->rdnis) 
241                                                         free(o->chan->rdnis);
242                                                 if (!ast_strlen_zero(in->macroexten))
243                                                         o->chan->rdnis = strdup(in->macroexten);
244                                                 else
245                                                         o->chan->rdnis = strdup(in->exten);
246                                                 if (ast_call(o->chan, tmpchan, 0)) {
247                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
248                                                         o->stillgoing = 0;
249                                                         ast_hangup(o->chan);
250                                                         o->chan = NULL;
251                                                         numbusies++;
252                                                 }
253                                         }
254                                         continue;
255                                 }
256                                 f = ast_read(winner);
257                                 if (f) {
258                                         if (f->frametype == AST_FRAME_CONTROL) {
259                                                 switch(f->subclass) {
260                                             case AST_CONTROL_ANSWER:
261                                                         /* This is our guy if someone answered. */
262                                                         if (!peer) {
263                                                                 if (option_verbose > 2)
264                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
265                                                                 peer = o->chan;
266                                                                 *allowredir_in = o->allowredirect_in;
267                                                                 *allowredir_out = o->allowredirect_out;
268                                                                 *allowdisconnect = o->allowdisconnect;
269                                                         }
270                                                         break;
271                                                 case AST_CONTROL_BUSY:
272                                                         if (option_verbose > 2)
273                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
274                                                         in->hangupcause = o->chan->hangupcause;
275                                                         ast_hangup(o->chan);
276                                                         o->chan = NULL;
277                                                         o->stillgoing = 0;
278                                                         if (in->cdr)
279                                                                 ast_cdr_busy(in->cdr);
280                                                         numbusies++;
281                                                         break;
282                                                 case AST_CONTROL_CONGESTION:
283                                                         if (option_verbose > 2)
284                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
285                                                         in->hangupcause = o->chan->hangupcause;
286                                                         ast_hangup(o->chan);
287                                                         o->chan = NULL;
288                                                         o->stillgoing = 0;
289                                                         if (in->cdr)
290                                                                 ast_cdr_busy(in->cdr);
291                                                         numbusies++;
292                                                         break;
293                                                 case AST_CONTROL_RINGING:
294                                                         if (option_verbose > 2)
295                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
296                                                         if (!sentringing && !moh) {
297                                                                 ast_indicate(in, AST_CONTROL_RINGING);
298                                                                 sentringing++;
299                                                         }
300                                                         break;
301                                                 case AST_CONTROL_PROGRESS:
302                                                         if (option_verbose > 2)
303                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
304                                                         ast_indicate(in, AST_CONTROL_PROGRESS);
305                                                         break;
306                                                 case AST_CONTROL_OFFHOOK:
307                                                         /* Ignore going off hook */
308                                                         break;
309                                                 case -1:
310                                                         if (!ringind && !moh) {
311                                                                 if (option_verbose > 2)
312                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
313                                                                 ast_indicate(in, -1);
314                                                                 sentringing = 0;
315                                                         }
316                                                         break;
317                                                 default:
318                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
319                                                 }
320                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
321                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
322                                                 if (ast_write(in, f)) 
323                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
324                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
325                                                                 !(outgoing->ringbackonly || outgoing->musiconhold)) {
326                                                 if (ast_write(in, f))
327                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
328                                         }
329                                         ast_frfree(f);
330                                 } else {
331                                         in->hangupcause = o->chan->hangupcause;
332                                         ast_hangup(o->chan);
333                                         o->chan = NULL;
334                                         o->stillgoing = 0;
335                                 }
336                         }
337                         o = o->next;
338                 }
339                 if (winner == in) {
340                         f = ast_read(in);
341 #if 0
342                         if (f && (f->frametype != AST_FRAME_VOICE))
343                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
344                         else if (!f || (f->frametype != AST_FRAME_VOICE))
345                                 printf("Hangup received on %s\n", in->name);
346 #endif
347                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
348                                 /* Got hung up */
349                                 *to=-1;
350                                 return NULL;
351                         }
352                         if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
353                                 (f->subclass == '*')) {
354                             if (option_verbose > 3)
355                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
356                                 *to=0;
357                                 return NULL;
358                         }
359                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
360                                 if (ast_write(outgoing->chan, f))
361                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
362                                 ast_frfree(f);
363                         }
364                 }
365                 if (!*to && (option_verbose > 2))
366                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
367         }
368         if (moh) {
369                 ast_moh_stop(in);
370         } else if (sentringing) {
371                 ast_indicate(in, -1);
372         }
373
374         return peer;
375         
376 }
377
378 static int dial_exec(struct ast_channel *chan, void *data)
379 {
380         int res=-1;
381         struct localuser *u;
382         char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
383         char  privdb[256] = "", *s;
384         char  announcemsg[256] = "", *ann;
385         struct localuser *outgoing=NULL, *tmp;
386         struct ast_channel *peer;
387         int to;
388         int allowredir_in=0;
389         int allowredir_out=0;
390         int allowdisconnect=0;
391         int privacy=0;
392         int announce=0;
393         int resetcdr=0;
394         char numsubst[AST_MAX_EXTENSION];
395         char restofit[AST_MAX_EXTENSION];
396         char *transfer = NULL;
397         char *newnum;
398         char callerid[256], *l, *n;
399         char *url=NULL; /* JDG */
400         struct ast_var_t *current;
401         struct varshead *headp, *newheadp;
402         struct ast_var_t *newvar;
403         int go_on=0;
404         unsigned int calldurationlimit=0;
405         char *cdl;
406         time_t now;
407         struct ast_bridge_config config;
408         long timelimit = 0;
409         long play_warning = 0;
410         long warning_freq=0;
411         char *warning_sound=NULL;
412         char *end_sound=NULL;
413         char *start_sound=NULL;
414         char *limitptr;
415         char limitdata[256];
416         char *sdtmfptr;
417         char sdtmfdata[256] = "";
418         char *stack,*var;
419         int play_to_caller=0,play_to_callee=0;
420         int playargs=0;
421         int digit = 0;
422
423         if (!data) {
424                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
425                 return -1;
426         }
427         
428         LOCAL_USER_ADD(u);
429         
430         strncpy(info, (char *)data, sizeof(info) - 1);
431         peers = info;
432         if (peers) {
433                 
434                 timeout = strchr(info, '|');
435                 if (timeout) {
436                         *timeout = '\0';
437                         timeout++;
438                         transfer = strchr(timeout, '|');
439                         if (transfer) {
440                                 *transfer = '\0';
441                                 transfer++;
442                                 /* JDG */
443                                 url = strchr(transfer, '|');
444                                 if (url) {
445                                         *url = '\0';
446                                         url++;
447                                         ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
448                                 } else 
449                                         ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
450                                 /* /JDG */
451                         }
452                 }
453         } else
454                 timeout = NULL;
455         if (!peers || ast_strlen_zero(peers)) {
456                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
457                 goto out;
458         }
459         
460
461         if (transfer) {
462
463                 /* Extract call duration limit */
464                 if ((cdl = strstr(transfer, "S("))) {
465                         calldurationlimit=atoi(cdl+2);
466                         if (option_verbose > 2)
467                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
468                 } 
469
470                 /* DTMF SCRIPT*/
471                 if ((sdtmfptr = strstr(transfer, "D("))) {
472                         strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
473                         /* Overwrite with X's what was the sdtmf info */
474                         while (*sdtmfptr && (*sdtmfptr != ')')) 
475                                 *(sdtmfptr++) = 'X';
476                         if (*sdtmfptr)
477                                 *sdtmfptr = 'X';
478                         /* Now find the end  */
479                         sdtmfptr = strchr(sdtmfdata, ')');
480                         if (sdtmfptr)
481                                 *sdtmfptr = '\0';
482                         else 
483                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
484                 }
485                 
486                 /* XXX LIMIT SUPPORT */
487                 if ((limitptr = strstr(transfer, "L("))) {
488                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
489                         /* Overwrite with X's what was the limit info */
490                         while(*limitptr && (*limitptr != ')')) 
491                                 *(limitptr++) = 'X';
492                         if (*limitptr)
493                                 *limitptr = 'X';
494                         /* Now find the end */
495                         limitptr = strchr(limitdata, ')');
496                         if (limitptr)
497                                 *limitptr = '\0';
498                         else
499                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
500
501                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
502                         play_to_caller = var ? ast_true(var) : 1;
503                   
504                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
505                         play_to_callee = var ? ast_true(var) : 0;
506                   
507                         if (!play_to_caller && !play_to_callee)
508                                 play_to_caller=1;
509                   
510                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
511                         warning_sound = var ? var : "timeleft";
512
513                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
514                         end_sound = var ? var : NULL;
515
516                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
517                         start_sound = var ? var : NULL;
518
519                         var=stack=limitdata;
520
521                         var = strsep(&stack, ":");
522                         if (var) {
523                                 timelimit = atol(var);
524                                 playargs++;
525                                 var = strsep(&stack, ":");
526                                 if (var) {
527                                         play_warning = atol(var);
528                                         playargs++;
529                                         var = strsep(&stack, ":");
530                                         if(var) {
531                                                 warning_freq = atol(var);
532                                                 playargs++;
533                                         }
534                                 }
535                         }
536                   
537                         if (!timelimit) {
538                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
539                                 warning_sound=NULL;
540                         }
541                         /* undo effect of S(x) in case they are both used */
542                         calldurationlimit=0; 
543                         /* more efficient do it like S(x) does since no advanced opts*/
544                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
545                                 calldurationlimit=timelimit/1000;
546                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
547                         } else if (option_verbose > 2) {
548                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
549                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
550                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
551                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
552                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
553                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
554                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
555                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
556                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
557                         }
558                 }
559                 
560                 /* XXX ANNOUNCE SUPPORT */
561                 if ((ann = strstr(transfer, "A("))) {
562                         announce = 1;
563                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
564                         /* Overwrite with X's what was the announce info */
565                         while(*ann && (*ann != ')')) 
566                                 *(ann++) = 'X';
567                         if (*ann)
568                                 *ann = 'X';
569                         /* Now find the end of the privdb */
570                         ann = strchr(announcemsg, ')');
571                         if (ann)
572                                 *ann = '\0';
573                         else {
574                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
575                                 announce = 0;
576                         }
577                 }
578                 /* Extract privacy info from transfer */
579                 if ((s = strstr(transfer, "P("))) {
580                         privacy = 1;
581                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
582                         /* Overwrite with X's what was the privacy info */
583                         while(*s && (*s != ')')) 
584                                 *(s++) = 'X';
585                         if (*s)
586                                 *s = 'X';
587                         /* Now find the end of the privdb */
588                         s = strchr(privdb, ')');
589                         if (s)
590                                 *s = '\0';
591                         else {
592                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
593                                 privacy = 0;
594                         }
595                 } else if (strchr(transfer, 'P')) {
596                         /* No specified privdb */
597                         privacy = 1;
598                 } else if (strchr(transfer, 'C')) {
599                         resetcdr = 1;
600                 }
601         }
602         if (resetcdr && chan->cdr)
603                 ast_cdr_reset(chan->cdr, 0);
604         if (ast_strlen_zero(privdb) && privacy) {
605                 /* If privdb is not specified and we are using privacy, copy from extension */
606                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
607         }
608         if (privacy) {
609                 if (chan->callerid)
610                         strncpy(callerid, chan->callerid, sizeof(callerid));
611                 else
612                         strcpy(callerid, "");
613                 ast_callerid_parse(callerid, &n, &l);
614                 if (l) {
615                         ast_shrink_phone_number(l);
616                 } else
617                         l = "";
618                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
619         }
620         cur = peers;
621         do {
622                 /* Remember where to start next time */
623                 rest = strchr(cur, '&');
624                 if (rest) {
625                         *rest = 0;
626                         rest++;
627                 }
628                 /* Get a technology/[device:]number pair */
629                 tech = cur;
630                 number = strchr(tech, '/');
631                 if (!number) {
632                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
633                         goto out;
634                 }
635                 *number = '\0';
636                 number++;
637                 tmp = malloc(sizeof(struct localuser));
638                 if (!tmp) {
639                         ast_log(LOG_WARNING, "Out of memory\n");
640                         goto out;
641                 }
642                 memset(tmp, 0, sizeof(struct localuser));
643                 if (transfer) {
644                         if (strchr(transfer, 't'))
645                                 tmp->allowredirect_in = 1;
646                         else    tmp->allowredirect_in = 0;
647                         if (strchr(transfer, 'T'))
648                                 tmp->allowredirect_out = 1;
649                         else    tmp->allowredirect_out = 0;
650                         if (strchr(transfer, 'r'))
651                                 tmp->ringbackonly = 1;
652                         else    tmp->ringbackonly = 0;
653                         if (strchr(transfer, 'm'))
654                                 tmp->musiconhold = 1;
655                         else    tmp->musiconhold = 0;
656                         if (strchr(transfer, 'H'))
657                                 allowdisconnect = tmp->allowdisconnect = 1;
658                         else    allowdisconnect = tmp->allowdisconnect = 0;
659                         if(strchr(transfer, 'g'))
660                                 go_on=1;
661                 }
662                 strncpy(numsubst, number, sizeof(numsubst)-1);
663                 /* If we're dialing by extension, look at the extension to know what to dial */
664                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
665                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
666                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
667                         if (option_debug)
668                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
669                 }
670                 /* Request the peer */
671                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst);
672                 if (!tmp->chan) {
673                         /* If we can't, just go on to the next call */
674                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", tech);
675                         if (chan->cdr)
676                                 ast_cdr_busy(chan->cdr);
677                         free(tmp);
678                         cur = rest;
679                         continue;
680                 }
681                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
682                         char tmpchan[256];
683                         if (option_verbose > 2)
684                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
685                         snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
686                         ast_hangup(tmp->chan);
687                         tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
688                         if (!tmp->chan) {
689                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
690                                 free(tmp);
691                                 cur = rest;
692                                 continue;
693                         }
694                 }
695                 /* If creating a SIP channel, look for a variable called */
696                 /* VXML_URL in the calling channel and copy it to the    */
697                 /* new channel.                                          */
698                 if (strcasecmp(tech,"SIP")==0)
699                 {
700                         headp=&chan->varshead;
701                         AST_LIST_TRAVERSE(headp,current,entries) {
702                                 if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
703                                 {
704                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
705                                         newheadp=&tmp->chan->varshead;
706                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
707                                         break;
708                                 }
709                         }
710                 }
711                 /* Check for ALERT_INFO in the SetVar list.  This is for   */
712                 /* SIP distinctive ring as per the RFC.  For Cisco 7960s,  */
713                 /* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
714                 /* However, the RFC says it should be a URL.  -km-         */
715
716                 if (strcasecmp(tech,"SIP")==0)
717                 {
718                         headp=&chan->varshead;
719                         AST_LIST_TRAVERSE(headp,current,entries) {
720                                 /* Search for ALERT_INFO */
721                                 if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
722                                 {
723                                         newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
724                                         newheadp=&tmp->chan->varshead;
725                                         AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
726                                         break;
727                                 }
728                         }
729                 }
730                 
731                 tmp->chan->appl = "AppDial";
732                 tmp->chan->data = "(Outgoing Line)";
733                 tmp->chan->whentohangup = 0;
734                 if (tmp->chan->callerid)
735                         free(tmp->chan->callerid);
736                 if (tmp->chan->ani)
737                         free(tmp->chan->ani);
738                 if (chan->callerid)
739                         tmp->chan->callerid = strdup(chan->callerid);
740                 else
741                         tmp->chan->callerid = NULL;
742                 /* Copy language from incoming to outgoing */
743                 strcpy(tmp->chan->language, chan->language);
744                 if (ast_strlen_zero(tmp->chan->musicclass))
745                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
746                 if (chan->ani)
747                         tmp->chan->ani = strdup(chan->ani);
748                 else
749                         tmp->chan->ani = NULL;
750                 /* Pass hidecallerid setting */
751                 tmp->chan->restrictcid = chan->restrictcid;
752                 /* Pass callingpres setting */
753                 tmp->chan->callingpres = chan->callingpres;
754                 /* Presense of ADSI CPE on outgoing channel follows ours */
755                 tmp->chan->adsicpe = chan->adsicpe;
756                 /* pass the digital flag */
757                 ast_dup_flag(tmp->chan, chan, AST_FLAG_DIGITAL);
758                 /* Place the call, but don't wait on the answer */
759                 res = ast_call(tmp->chan, numsubst, 0);
760
761                 /* Save the info in cdr's that we called them */
762                 if (chan->cdr)
763                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
764
765                 /* check the restuls of ast_call */
766                 if (res) {
767                         /* Again, keep going even if there's an error */
768                         if (option_debug)
769                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
770                         else if (option_verbose > 2)
771                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
772                         ast_hangup(tmp->chan);
773                         free(tmp);
774                         cur = rest;
775                         continue;
776                 } else
777                         if (option_verbose > 2)
778                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
779                 /* Put them in the list of outgoing thingies...  We're ready now. 
780                    XXX If we're forcibly removed, these outgoing calls won't get
781                    hung up XXX */
782                 tmp->stillgoing = -1;
783                 tmp->next = outgoing;
784                 outgoing = tmp;
785                 /* If this line is up, don't try anybody else */
786                 if (outgoing->chan->_state == AST_STATE_UP)
787                         break;
788                 cur = rest;
789         } while(cur);
790         
791         if (timeout && !ast_strlen_zero(timeout)) {
792                 to = atoi(timeout);
793                 if (to > 0)
794                         to *= 1000;
795                 else
796                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
797         } else
798                 to = -1;
799         peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
800         if (!peer) {
801                 if (to) 
802                         /* Musta gotten hung up */
803                         res = -1;
804                  else 
805                         /* Nobody answered, next please? */
806                         res=0;
807                 
808                 goto out;
809         }
810         if (peer) {
811                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
812                    we will always return with -1 so that it is hung up properly after the 
813                    conversation.  */
814                 hanguptree(outgoing, peer);
815                 outgoing = NULL;
816                 /* If appropriate, log that we have a destination channel */
817                 if (chan->cdr)
818                         ast_cdr_setdestchan(chan->cdr, peer->name);
819                 if (peer->name)
820                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
821                 if (numsubst)
822                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
823                 /* Make sure channels are compatible */
824                 res = ast_channel_make_compatible(chan, peer);
825                 if (res < 0) {
826                         ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
827                         ast_hangup(peer);
828                         return -1;
829                 }
830                 /* JDG: sendurl */
831                 if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
832                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
833                         ast_channel_sendurl( peer, url );
834                 } /* /JDG */
835                 if (announce && announcemsg) {
836                         // Start autoservice on the other chan
837                         res = ast_autoservice_start(chan);
838                         // Now Stream the File
839                         if (!res)
840                                 res = ast_streamfile(peer,announcemsg,peer->language);
841                         if (!res) {
842                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
843                         }
844                         // Ok, done. stop autoservice
845                         res = ast_autoservice_stop(chan);
846                         if (digit > 0 && !res)
847                                 res = ast_senddigit(chan, digit); 
848                         else
849                                 res = digit;
850
851                 } else
852                         res = 0;
853
854                 if (!res) {
855                         if (calldurationlimit > 0) {
856                                 time(&now);
857                                 chan->whentohangup = now + calldurationlimit;
858                         }
859                         if (!ast_strlen_zero(sdtmfdata)) 
860                                 res = ast_dtmf_stream(peer,chan,sdtmfdata,0);
861                 }
862                 
863                 if (!res) {
864                         memset(&config,0,sizeof(struct ast_bridge_config));
865                         config.play_to_caller=play_to_caller;
866                         config.play_to_callee=play_to_callee;
867                         config.allowredirect_in = allowredir_in;
868                         config.allowredirect_out = allowredir_out;
869                         config.allowdisconnect = allowdisconnect;
870                         config.timelimit = timelimit;
871                         config.play_warning = play_warning;
872                         config.warning_freq = warning_freq;
873                         config.warning_sound = warning_sound;
874                         config.end_sound = end_sound;
875                         config.start_sound = start_sound;
876                         res = ast_bridge_call(chan,peer,&config);
877                 } else 
878                         res = -1;
879                 
880                 if (res != AST_PBX_NO_HANGUP_PEER) {
881                         if (!chan->_softhangup)
882                                 chan->hangupcause = peer->hangupcause;
883                         ast_hangup(peer);
884                 }
885         }       
886 out:
887         hanguptree(outgoing, NULL);
888         LOCAL_USER_REMOVE(u);
889         
890         if((go_on>0) && (!chan->_softhangup))
891             res=0;
892             
893         return res;
894 }
895
896 int unload_module(void)
897 {
898         STANDARD_HANGUP_LOCALUSERS;
899         return ast_unregister_application(app);
900 }
901
902 int load_module(void)
903 {
904         int res;
905         res = ast_register_application(app, dial_exec, synopsis, descrip);
906         return res;
907 }
908
909 char *description(void)
910 {
911         return tdesc;
912 }
913
914 int usecount(void)
915 {
916         int res;
917         STANDARD_USECOUNT(res);
918         return res;
919 }
920
921 char *key()
922 {
923         return ASTERISK_GPL_KEY;
924 }