CHANGES: Update changes log to include r403414 entry
[asterisk/asterisk.git] / apps / app_chanspy.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
5  * Copyright (C) 2005 - 2008, Digium, Inc.
6  *
7  * A license has been granted to Digium (via disclaimer) for the use of
8  * this code.
9  *
10  * See http://www.asterisk.org for more information about
11  * the Asterisk project. Please do not directly contact
12  * any of the maintainers of this project for assistance;
13  * the project provides a web site, mailing lists and IRC
14  * channels for your use.
15  *
16  * This program is free software, distributed under the terms of
17  * the GNU General Public License Version 2. See the LICENSE file
18  * at the top of the source tree.
19  */
20
21 /*! \file
22  *
23  * \brief ChanSpy: Listen in on any channel.
24  *
25  * \author Anthony Minessale II <anthmct@yahoo.com>
26  * \author Joshua Colp <jcolp@digium.com>
27  * \author Russell Bryant <russell@digium.com>
28  *
29  * \ingroup applications
30  */
31
32 /*** MODULEINFO
33         <support_level>core</support_level>
34  ***/
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include <ctype.h>
41 #include <errno.h>
42
43 #include "asterisk/paths.h" /* use ast_config_AST_MONITOR_DIR */
44 #include "asterisk/file.h"
45 #include "asterisk/channel.h"
46 #include "asterisk/audiohook.h"
47 #include "asterisk/features.h"
48 #include "asterisk/app.h"
49 #include "asterisk/utils.h"
50 #include "asterisk/say.h"
51 #include "asterisk/pbx.h"
52 #include "asterisk/translate.h"
53 #include "asterisk/manager.h"
54 #include "asterisk/module.h"
55 #include "asterisk/lock.h"
56 #include "asterisk/options.h"
57 #include "asterisk/autochan.h"
58 #include "asterisk/stasis_channels.h"
59 #include "asterisk/json.h"
60
61 #define AST_NAME_STRLEN 256
62 #define NUM_SPYGROUPS 128
63
64 /*** DOCUMENTATION
65         <application name="ChanSpy" language="en_US">
66                 <synopsis>
67                         Listen to a channel, and optionally whisper into it.
68                 </synopsis>
69                 <syntax>
70                         <parameter name="chanprefix" />
71                         <parameter name="options">
72                                 <optionlist>
73                                         <option name="b">
74                                                 <para>Only spy on channels involved in a bridged call.</para>
75                                         </option>
76                                         <option name="B">
77                                                 <para>Instead of whispering on a single channel barge in on both
78                                                 channels involved in the call.</para>
79                                         </option>
80                                         <option name="c">
81                                                 <argument name="digit" required="true">
82                                                         <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
83                                                 </argument>
84                                         </option>
85                                         <option name="d">
86                                                 <para>Override the typical numeric DTMF functionality and instead
87                                                 use DTMF to switch between spy modes.</para>
88                                                 <enumlist>
89                                                         <enum name="4">
90                                                                 <para>spy mode</para>
91                                                         </enum>
92                                                         <enum name="5">
93                                                                 <para>whisper mode</para>
94                                                         </enum>
95                                                         <enum name="6">
96                                                                 <para>barge mode</para>
97                                                         </enum>
98                                                 </enumlist>
99                                         </option>
100                                         <option name="e">
101                                                 <argument name="ext" required="true" />
102                                                 <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
103                                                 only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
104                                                 list.</para>
105                                         </option>
106                                         <option name="E">
107                                                 <para>Exit when the spied-on channel hangs up.</para>
108                                         </option>
109                                         <option name="g">
110                                                 <argument name="grp" required="true">
111                                                         <para>Only spy on channels in which one or more of the groups
112                                                         listed in <replaceable>grp</replaceable> matches one or more groups from the
113                                                         <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
114                                                 </argument>
115                                                 <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
116                                                 either a single group or a colon-delimited list of groups, such
117                                                 as <literal>sales:support:accounting</literal>.</para></note>
118                                         </option>
119                                         <option name="n" argsep="@">
120                                                 <para>Say the name of the person being spied on if that person has recorded
121                                                 his/her name. If a context is specified, then that voicemail context will
122                                                 be searched when retrieving the name, otherwise the <literal>default</literal> context
123                                                 be used when searching for the name (i.e. if SIP/1000 is the channel being
124                                                 spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
125                                                 for the name).</para>
126                                                 <argument name="mailbox" />
127                                                 <argument name="context" />
128                                         </option>
129                                         <option name="o">
130                                                 <para>Only listen to audio coming from this channel.</para>
131                                         </option>
132                                         <option name="q">
133                                                 <para>Don't play a beep when beginning to spy on a channel, or speak the
134                                                 selected channel name.</para>
135                                         </option>
136                                         <option name="r">
137                                                 <para>Record the session to the monitor spool directory. An optional base for the filename 
138                                                 may be specified. The default is <literal>chanspy</literal>.</para>
139                                                 <argument name="basename" />
140                                         </option>
141                                         <option name="s">
142                                                 <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
143                                                 speaking the selected channel name.</para>
144                                         </option>
145                                         <option name="S">
146                                                 <para>Stop when no more channels are left to spy on.</para>
147                                         </option>
148                                         <option name="u">
149                                                 <para>The <literal>chanprefix</literal> parameter is a channel uniqueid
150                                                 or fully specified channel name.</para>
151                                         </option>
152                                         <option name="v">
153                                                 <argument name="value" />
154                                                 <para>Adjust the initial volume in the range from <literal>-4</literal> 
155                                                 to <literal>4</literal>. A negative value refers to a quieter setting.</para>
156                                         </option>
157                                         <option name="w">
158                                                 <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
159                                                 the spied-on channel.</para>
160                                         </option>
161                                         <option name="W">
162                                                 <para>Enable <literal>private whisper</literal> mode, so the spying channel can
163                                                 talk to the spied-on channel but cannot listen to that channel.</para>
164                                         </option>
165                                         <option name="x">
166                                                 <argument name="digit" required="true">
167                                                         <para>Specify a DTMF digit that can be used to exit the application.</para>
168                                                 </argument>
169                                         </option>
170                                         <option name="X">
171                                                 <para>Allow the user to exit ChanSpy to a valid single digit
172                                                 numeric extension in the current context or the context
173                                                 specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
174                                                 name of the last channel that was spied on will be stored
175                                                 in the <variable>SPY_CHANNEL</variable> variable.</para>
176                                         </option>
177                                 </optionlist>           
178                         </parameter>
179                 </syntax>
180                 <description>
181                         <para>This application is used to listen to the audio from an Asterisk channel. This includes the audio 
182                         coming in and out of the channel being spied on. If the <literal>chanprefix</literal> parameter is specified,
183                         only channels beginning with this string will be spied upon.</para>
184                         <para>While spying, the following actions may be performed:</para>
185                         <para> - Dialing <literal>#</literal> cycles the volume level.</para>
186                         <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
187                         <para> - Dialing a series of digits followed by <literal>#</literal> builds a channel name to append
188                         to <literal>chanprefix</literal>. For example, executing ChanSpy(Agent) and then dialing the digits '1234#'
189                         while spying will begin spying on the channel 'Agent/1234'. Note that this feature will be overridden
190                         if the 'd' or 'u' options are used.</para>
191                         <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
192                         single digit extension exists in the correct context ChanSpy will exit to it.
193                         This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
194                 </description>
195                 <see-also>
196                         <ref type="application">ExtenSpy</ref>
197                         <ref type="managerEvent">ChanSpyStart</ref>
198                         <ref type="managerEvent">ChanSpyStop</ref>
199                 </see-also>
200         </application>
201         <application name="ExtenSpy" language="en_US">
202                 <synopsis>
203                         Listen to a channel, and optionally whisper into it.
204                 </synopsis>
205                 <syntax>
206                         <parameter name="exten" required="true" argsep="@">
207                                 <argument name="exten" required="true">
208                                         <para>Specify extension.</para>
209                                 </argument>
210                                 <argument name="context">
211                                         <para>Optionally specify a context, defaults to <literal>default</literal>.</para>
212                                 </argument>
213                         </parameter>
214                         <parameter name="options">
215                                 <optionlist>
216                                         <option name="b">
217                                                 <para>Only spy on channels involved in a bridged call.</para>
218                                         </option>
219                                         <option name="B">
220                                                 <para>Instead of whispering on a single channel barge in on both
221                                                 channels involved in the call.</para>
222                                         </option>
223                                         <option name="c">
224                                                 <argument name="digit" required="true">
225                                                         <para>Specify a DTMF digit that can be used to spy on the next available channel.</para>
226                                                 </argument>
227                                         </option>
228                                         <option name="d">
229                                                 <para>Override the typical numeric DTMF functionality and instead
230                                                 use DTMF to switch between spy modes.</para>
231                                                 <enumlist>
232                                                         <enum name="4">
233                                                                 <para>spy mode</para>
234                                                         </enum>
235                                                         <enum name="5">
236                                                                 <para>whisper mode</para>
237                                                         </enum>
238                                                         <enum name="6">
239                                                                 <para>barge mode</para>
240                                                         </enum>
241                                                 </enumlist>
242                                         </option>
243                                         <option name="e">
244                                                 <argument name="ext" required="true" />
245                                                 <para>Enable <emphasis>enforced</emphasis> mode, so the spying channel can
246                                                 only monitor extensions whose name is in the <replaceable>ext</replaceable> : delimited 
247                                                 list.</para>
248                                         </option>
249                                         <option name="E">
250                                                 <para>Exit when the spied-on channel hangs up.</para>
251                                         </option>
252                                         <option name="g">
253                                                 <argument name="grp" required="true">
254                                                         <para>Only spy on channels in which one or more of the groups
255                                                         listed in <replaceable>grp</replaceable> matches one or more groups from the
256                                                         <variable>SPYGROUP</variable> variable set on the channel to be spied upon.</para>
257                                                 </argument>
258                                                 <note><para>both <replaceable>grp</replaceable> and <variable>SPYGROUP</variable> can contain 
259                                                 either a single group or a colon-delimited list of groups, such
260                                                 as <literal>sales:support:accounting</literal>.</para></note>
261                                         </option>
262                                         <option name="n" argsep="@">
263                                                 <para>Say the name of the person being spied on if that person has recorded
264                                                 his/her name. If a context is specified, then that voicemail context will
265                                                 be searched when retrieving the name, otherwise the <literal>default</literal> context
266                                                 be used when searching for the name (i.e. if SIP/1000 is the channel being
267                                                 spied on and no mailbox is specified, then <literal>1000</literal> will be used when searching
268                                                 for the name).</para>
269                                                 <argument name="mailbox" />
270                                                 <argument name="context" />
271                                         </option>
272                                         <option name="o">
273                                                 <para>Only listen to audio coming from this channel.</para>
274                                         </option>
275                                         <option name="q">
276                                                 <para>Don't play a beep when beginning to spy on a channel, or speak the
277                                                 selected channel name.</para>
278                                         </option>
279                                         <option name="r">
280                                                 <para>Record the session to the monitor spool directory. An optional base for the filename 
281                                                 may be specified. The default is <literal>chanspy</literal>.</para>
282                                                 <argument name="basename" />
283                                         </option>
284                                         <option name="s">
285                                                 <para>Skip the playback of the channel type (i.e. SIP, IAX, etc) when
286                                                 speaking the selected channel name.</para>
287                                         </option>
288                                         <option name="S">
289                                                 <para>Stop when there are no more extensions left to spy on.</para>
290                                         </option>
291                                         <option name="v">
292                                                 <argument name="value" />
293                                                 <para>Adjust the initial volume in the range from <literal>-4</literal> 
294                                                 to <literal>4</literal>. A negative value refers to a quieter setting.</para>
295                                         </option>
296                                         <option name="w">
297                                                 <para>Enable <literal>whisper</literal> mode, so the spying channel can talk to
298                                                 the spied-on channel.</para>
299                                         </option>
300                                         <option name="W">
301                                                 <para>Enable <literal>private whisper</literal> mode, so the spying channel can
302                                                 talk to the spied-on channel but cannot listen to that channel.</para>
303                                         </option>
304                                         <option name="x">
305                                                 <argument name="digit" required="true">
306                                                         <para>Specify a DTMF digit that can be used to exit the application.</para>
307                                                 </argument>
308                                         </option>
309                                         <option name="X">
310                                                 <para>Allow the user to exit ChanSpy to a valid single digit
311                                                 numeric extension in the current context or the context
312                                                 specified by the <variable>SPY_EXIT_CONTEXT</variable> channel variable. The
313                                                 name of the last channel that was spied on will be stored
314                                                 in the <variable>SPY_CHANNEL</variable> variable.</para>
315                                         </option>
316                                 </optionlist>   
317                         </parameter>
318                 </syntax>
319                 <description>
320                         <para>This application is used to listen to the audio from an Asterisk channel. This includes 
321                         the audio coming in and out of the channel being spied on. Only channels created by outgoing calls for the
322                         specified extension will be selected for spying. If the optional context is not supplied, 
323                         the current channel's context will be used.</para>
324                         <para>While spying, the following actions may be performed:</para>
325                         <para> - Dialing <literal>#</literal> cycles the volume level.</para>
326                         <para> - Dialing <literal>*</literal> will stop spying and look for another channel to spy on.</para>
327                         <note><para>The <replaceable>X</replaceable> option supersedes the three features above in that if a valid
328                         single digit extension exists in the correct context ChanSpy will exit to it.
329                         This also disables choosing a channel based on <literal>chanprefix</literal> and a digit sequence.</para></note>
330                 </description>
331                 <see-also>
332                         <ref type="application">ChanSpy</ref>
333                         <ref type="managerEvent">ChanSpyStart</ref>
334                         <ref type="managerEvent">ChanSpyStop</ref>
335                 </see-also>
336         </application>
337         <application name="DAHDIScan" language="en_US">
338                 <synopsis>
339                         Scan DAHDI channels to monitor calls.
340                 </synopsis>
341                 <syntax>
342                         <parameter name="group">
343                                 <para>Limit scanning to a channel <replaceable>group</replaceable> by setting this option.</para>
344                         </parameter>
345                 </syntax>
346                 <description>
347                         <para>Allows a call center manager to monitor DAHDI channels in a
348                         convenient way.  Use <literal>#</literal> to select the next channel and use <literal>*</literal> to exit.</para>
349                 </description>
350                 <see-also>
351                         <ref type="managerEvent">ChanSpyStart</ref>
352                         <ref type="managerEvent">ChanSpyStop</ref>
353                 </see-also>
354         </application>
355  ***/
356
357 static const char app_chan[] = "ChanSpy";
358
359 static const char app_ext[] = "ExtenSpy";
360
361 static const char app_dahdiscan[] = "DAHDIScan";
362
363 enum {
364         OPTION_QUIET             = (1 << 0),    /* Quiet, no announcement */
365         OPTION_BRIDGED           = (1 << 1),    /* Only look at bridged calls */
366         OPTION_VOLUME            = (1 << 2),    /* Specify initial volume */
367         OPTION_GROUP             = (1 << 3),    /* Only look at channels in group */
368         OPTION_RECORD            = (1 << 4),
369         OPTION_WHISPER           = (1 << 5),
370         OPTION_PRIVATE           = (1 << 6),    /* Private Whisper mode */
371         OPTION_READONLY          = (1 << 7),    /* Don't mix the two channels */
372         OPTION_EXIT              = (1 << 8),    /* Exit to a valid single digit extension */
373         OPTION_ENFORCED          = (1 << 9),    /* Enforced mode */
374         OPTION_NOTECH            = (1 << 10),   /* Skip technology name playback */
375         OPTION_BARGE             = (1 << 11),   /* Barge mode (whisper to both channels) */
376         OPTION_NAME              = (1 << 12),   /* Say the name of the person on whom we will spy */
377         OPTION_DTMF_SWITCH_MODES = (1 << 13),   /* Allow numeric DTMF to switch between chanspy modes */
378         OPTION_DTMF_EXIT         = (1 << 14),   /* Set DTMF to exit, added for DAHDIScan integration */
379         OPTION_DTMF_CYCLE        = (1 << 15),   /* Custom DTMF for cycling next available channel, (default is '*') */
380         OPTION_DAHDI_SCAN        = (1 << 16),   /* Scan groups in DAHDIScan mode */
381         OPTION_STOP              = (1 << 17),
382         OPTION_EXITONHANGUP      = (1 << 18),   /* Hang up when the spied-on channel hangs up. */
383         OPTION_UNIQUEID          = (1 << 19),   /* The chanprefix is a channel uniqueid or fully specified channel name. */
384 };
385
386 enum {
387         OPT_ARG_VOLUME = 0,
388         OPT_ARG_GROUP,
389         OPT_ARG_RECORD,
390         OPT_ARG_ENFORCED,
391         OPT_ARG_NAME,
392         OPT_ARG_EXIT,
393         OPT_ARG_CYCLE,
394         OPT_ARG_ARRAY_SIZE,
395 };
396
397 AST_APP_OPTIONS(spy_opts, {
398         AST_APP_OPTION('b', OPTION_BRIDGED),
399         AST_APP_OPTION('B', OPTION_BARGE),
400         AST_APP_OPTION_ARG('c', OPTION_DTMF_CYCLE, OPT_ARG_CYCLE),
401         AST_APP_OPTION('d', OPTION_DTMF_SWITCH_MODES),
402         AST_APP_OPTION_ARG('e', OPTION_ENFORCED, OPT_ARG_ENFORCED),
403         AST_APP_OPTION('E', OPTION_EXITONHANGUP),
404         AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
405         AST_APP_OPTION_ARG('n', OPTION_NAME, OPT_ARG_NAME),
406         AST_APP_OPTION('o', OPTION_READONLY),
407         AST_APP_OPTION('q', OPTION_QUIET),
408         AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
409         AST_APP_OPTION('s', OPTION_NOTECH),
410         AST_APP_OPTION('S', OPTION_STOP),
411         AST_APP_OPTION('u', OPTION_UNIQUEID),
412         AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
413         AST_APP_OPTION('w', OPTION_WHISPER),
414         AST_APP_OPTION('W', OPTION_PRIVATE),
415         AST_APP_OPTION_ARG('x', OPTION_DTMF_EXIT, OPT_ARG_EXIT),
416         AST_APP_OPTION('X', OPTION_EXIT),
417 });
418
419 struct chanspy_translation_helper {
420         /* spy data */
421         struct ast_audiohook spy_audiohook;
422         struct ast_audiohook whisper_audiohook;
423         struct ast_audiohook bridge_whisper_audiohook;
424         int fd;
425         int volfactor;
426         struct ast_flags flags;
427 };
428
429 struct spy_dtmf_options {
430         char exit;
431         char cycle;
432         char volume;
433 };
434
435 static void *spy_alloc(struct ast_channel *chan, void *data)
436 {
437         /* just store the data pointer in the channel structure */
438         return data;
439 }
440
441 static void spy_release(struct ast_channel *chan, void *data)
442 {
443         /* nothing to do */
444 }
445
446 static int spy_generate(struct ast_channel *chan, void *data, int len, int samples)
447 {
448         struct chanspy_translation_helper *csth = data;
449         struct ast_frame *f, *cur;
450         struct ast_format format_slin;
451
452         ast_format_set(&format_slin, AST_FORMAT_SLINEAR, 0);
453
454         ast_audiohook_lock(&csth->spy_audiohook);
455         if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
456                 /* Channel is already gone more than likely */
457                 ast_audiohook_unlock(&csth->spy_audiohook);
458                 return -1;
459         }
460
461         if (ast_test_flag(&csth->flags, OPTION_READONLY)) {
462                 /* Option 'o' was set, so don't mix channel audio */
463                 f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_READ, &format_slin);
464         } else {
465                 f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, &format_slin);
466         }
467
468         ast_audiohook_unlock(&csth->spy_audiohook);
469
470         if (!f)
471                 return 0;
472
473         for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
474                 if (ast_write(chan, cur)) {
475                         ast_frfree(f);
476                         return -1;
477                 }
478
479                 if (csth->fd) {
480                         if (write(csth->fd, cur->data.ptr, cur->datalen) < 0) {
481                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
482                         }
483                 }
484         }
485
486         ast_frfree(f);
487
488         return 0;
489 }
490
491 static struct ast_generator spygen = {
492         .alloc = spy_alloc,
493         .release = spy_release,
494         .generate = spy_generate,
495 };
496
497 static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
498 {
499         int res = 0;
500
501         ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
502
503         ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
504         res = ast_audiohook_attach(autochan->chan, audiohook);
505
506         if (!res) {
507                 ast_channel_lock(autochan->chan);
508                 if (ast_channel_is_bridged(autochan->chan)) {
509                         ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE);
510                 }
511                 ast_channel_unlock(autochan->chan);
512         }
513         return res;
514 }
515
516 static void change_spy_mode(const char digit, struct ast_flags *flags)
517 {
518         if (digit == '4') {
519                 ast_clear_flag(flags, OPTION_WHISPER);
520                 ast_clear_flag(flags, OPTION_BARGE);
521         } else if (digit == '5') {
522                 ast_clear_flag(flags, OPTION_BARGE);
523                 ast_set_flag(flags, OPTION_WHISPER);
524         } else if (digit == '6') {
525                 ast_clear_flag(flags, OPTION_WHISPER);
526                 ast_set_flag(flags, OPTION_BARGE);
527         }
528 }
529
530 static int pack_channel_into_message(struct ast_channel *chan, const char *role,
531                                                                          struct ast_multi_channel_blob *payload)
532 {
533         RAII_VAR(struct ast_channel_snapshot *, snapshot,
534                         ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)),
535                         ao2_cleanup);
536
537         if (!snapshot) {
538                 return -1;
539         }
540         ast_multi_channel_blob_add_channel(payload, role, snapshot);
541         return 0;
542 }
543
544 /*! \internal
545  * \brief Publish the chanspy message over Stasis-Core
546  * \param spyer The channel doing the spying
547  * \param spyee Who is being spied upon
548  * \start start If non-zero, the spying is starting. Otherwise, the spyer is
549  * finishing
550  */
551 static void publish_chanspy_message(struct ast_channel *spyer,
552                                                                         struct ast_channel *spyee,
553                                                                         int start)
554 {
555         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
556         RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
557         RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
558
559         if (!spyer) {
560                 ast_log(AST_LOG_WARNING, "Attempt to publish ChanSpy message for NULL spyer channel\n");
561                 return;
562         }
563         blob = ast_json_null();
564         if (!blob) {
565                 return;
566         }
567
568         payload = ast_multi_channel_blob_create(blob);
569         if (!payload) {
570                 return;
571         }
572
573         if (pack_channel_into_message(spyer, "spyer_channel", payload)) {
574                 return;
575         }
576
577         if (spyee) {
578                 if (pack_channel_into_message(spyee, "spyee_channel", payload)) {
579                         return;
580                 }
581         }
582
583         message = stasis_message_create(
584                         start ? ast_channel_chanspy_start_type(): ast_channel_chanspy_stop_type(),
585                                         payload);
586         if (!message) {
587                 return;
588         }
589         stasis_publish(ast_channel_topic(spyer), message);
590 }
591
592 static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
593         int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
594         char *exitcontext)
595 {
596         struct chanspy_translation_helper csth;
597         int running = 0, res, x = 0;
598         char inp[24] = {0};
599         char *name;
600         struct ast_frame *f;
601         struct ast_silence_generator *silgen = NULL;
602         struct ast_autochan *spyee_bridge_autochan = NULL;
603         const char *spyer_name;
604
605         if (ast_check_hangup(chan) || ast_check_hangup(spyee_autochan->chan) ||
606                         ast_test_flag(ast_channel_flags(spyee_autochan->chan), AST_FLAG_ZOMBIE)) {
607                 return 0;
608         }
609
610         ast_channel_lock(chan);
611         spyer_name = ast_strdupa(ast_channel_name(chan));
612         ast_channel_unlock(chan);
613
614         ast_channel_lock(spyee_autochan->chan);
615         name = ast_strdupa(ast_channel_name(spyee_autochan->chan));
616         ast_channel_unlock(spyee_autochan->chan);
617
618         ast_verb(2, "Spying on channel %s\n", name);
619         publish_chanspy_message(chan, spyee_autochan->chan, 1);
620
621         memset(&csth, 0, sizeof(csth));
622         ast_copy_flags(&csth.flags, flags, AST_FLAGS_ALL);
623
624         /* This is the audiohook which gives us the audio off the channel we are
625            spying on.
626         */
627         ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy", 0);
628
629         if (start_spying(spyee_autochan, spyer_name, &csth.spy_audiohook)) {
630                 ast_audiohook_destroy(&csth.spy_audiohook);
631                 return 0;
632         }
633
634         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
635                 /* This audiohook will let us inject audio from our channel into the
636                    channel we are currently spying on.
637                 */
638                 ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy", 0);
639
640                 if (start_spying(spyee_autochan, spyer_name, &csth.whisper_audiohook)) {
641                         ast_log(LOG_WARNING, "Unable to attach whisper audiohook to spyee %s. Whisper mode disabled!\n", name);
642                 }
643         }
644
645         if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
646                 RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(spyee_autochan->chan), ast_channel_cleanup);
647
648                 /* And this hook lets us inject audio into the channel that the spied on
649                    channel is currently bridged with.
650                 */
651                 ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
652
653                 if ((spyee_bridge_autochan = ast_autochan_setup(bridged))) {
654                         ast_channel_lock(spyee_bridge_autochan->chan);
655                         if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
656                                 ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
657                         }
658                         ast_channel_unlock(spyee_bridge_autochan->chan);
659                 }
660         }
661
662         ast_channel_lock(chan);
663         ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
664         ast_channel_unlock(chan);
665
666         csth.volfactor = *volfactor;
667
668         if (csth.volfactor) {
669                 csth.spy_audiohook.options.read_volume = csth.volfactor;
670                 csth.spy_audiohook.options.write_volume = csth.volfactor;
671         }
672
673         csth.fd = fd;
674
675         if (ast_test_flag(flags, OPTION_PRIVATE))
676                 silgen = ast_channel_start_silence_generator(chan);
677         else
678                 ast_activate_generator(chan, &spygen, &csth);
679
680         /* We can no longer rely on 'spyee' being an actual channel;
681            it can be hung up and freed out from under us. However, the
682            channel destructor will put NULL into our csth.spy.chan
683            field when that happens, so that is our signal that the spyee
684            channel has gone away.
685         */
686
687         /* Note: it is very important that the ast_waitfor() be the first
688            condition in this expression, so that if we wait for some period
689            of time before receiving a frame from our spying channel, we check
690            for hangup on the spied-on channel _after_ knowing that a frame
691            has arrived, since the spied-on channel could have gone away while
692            we were waiting
693         */
694         while (ast_waitfor(chan, -1) > -1 && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
695                 if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
696                         running = -1;
697                         break;
698                 }
699
700                 if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
701                         ast_audiohook_lock(&csth.whisper_audiohook);
702                         ast_audiohook_lock(&csth.bridge_whisper_audiohook);
703                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
704                         ast_audiohook_write_frame(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
705                         ast_audiohook_unlock(&csth.whisper_audiohook);
706                         ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
707                         ast_frfree(f);
708                         continue;
709                 } else if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
710                         ast_audiohook_lock(&csth.whisper_audiohook);
711                         ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
712                         ast_audiohook_unlock(&csth.whisper_audiohook);
713                         ast_frfree(f);
714                         continue;
715                 }
716                 
717                 res = (f->frametype == AST_FRAME_DTMF) ? f->subclass.integer : 0;
718                 ast_frfree(f);
719                 if (!res)
720                         continue;
721
722                 if (x == sizeof(inp))
723                         x = 0;
724
725                 if (res < 0) {
726                         running = -1;
727                         break;
728                 }
729
730                 if (ast_test_flag(flags, OPTION_EXIT)) {
731                         char tmp[2];
732                         tmp[0] = res;
733                         tmp[1] = '\0';
734                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
735                                 ast_debug(1, "Got DTMF %c, goto context %s\n", tmp[0], exitcontext);
736                                 pbx_builtin_setvar_helper(chan, "SPY_CHANNEL", name);
737                                 running = -2;
738                                 break;
739                         } else {
740                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
741                         }
742                 } else if (res >= '0' && res <= '9') {
743                         if (ast_test_flag(flags, OPTION_DTMF_SWITCH_MODES)) {
744                                 change_spy_mode(res, flags);
745                         } else {
746                                 inp[x++] = res;
747                         }
748                 }
749
750                 if (res == user_options->cycle) {
751                         running = 0;
752                         break;
753                 } else if (res == user_options->exit) {
754                         running = -2;
755                         break;
756                 } else if (res == user_options->volume) {
757                         if (!ast_strlen_zero(inp)) {
758                                 running = atoi(inp);
759                                 break;
760                         }
761
762                         (*volfactor)++;
763                         if (*volfactor > 4)
764                                 *volfactor = -4;
765                         ast_verb(3, "Setting spy volume on %s to %d\n", ast_channel_name(chan), *volfactor);
766
767                         csth.volfactor = *volfactor;
768                         csth.spy_audiohook.options.read_volume = csth.volfactor;
769                         csth.spy_audiohook.options.write_volume = csth.volfactor;
770                 }
771         }
772
773         if (ast_test_flag(flags, OPTION_PRIVATE))
774                 ast_channel_stop_silence_generator(chan, silgen);
775         else
776                 ast_deactivate_generator(chan);
777
778         ast_channel_lock(chan);
779         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
780         ast_channel_unlock(chan);
781
782         if (ast_test_flag(flags, OPTION_WHISPER | OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
783                 ast_audiohook_lock(&csth.whisper_audiohook);
784                 ast_audiohook_detach(&csth.whisper_audiohook);
785                 ast_audiohook_unlock(&csth.whisper_audiohook);
786                 ast_audiohook_destroy(&csth.whisper_audiohook);
787         }
788
789         if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
790                 ast_audiohook_lock(&csth.bridge_whisper_audiohook);
791                 ast_audiohook_detach(&csth.bridge_whisper_audiohook);
792                 ast_audiohook_unlock(&csth.bridge_whisper_audiohook);
793                 ast_audiohook_destroy(&csth.bridge_whisper_audiohook);
794         }
795
796         ast_audiohook_lock(&csth.spy_audiohook);
797         ast_audiohook_detach(&csth.spy_audiohook);
798         ast_audiohook_unlock(&csth.spy_audiohook);
799         ast_audiohook_destroy(&csth.spy_audiohook);
800
801         if (spyee_bridge_autochan) {
802                 ast_autochan_destroy(spyee_bridge_autochan);
803         }
804
805         ast_verb(2, "Done Spying on channel %s\n", name);
806         publish_chanspy_message(chan, NULL, 0);
807
808         return running;
809 }
810
811 static struct ast_autochan *next_channel(struct ast_channel_iterator *iter,
812                 struct ast_autochan *autochan, struct ast_channel *chan)
813 {
814         struct ast_channel *next;
815         struct ast_autochan *autochan_store;
816         const size_t pseudo_len = strlen("DAHDI/pseudo");
817
818         if (!iter) {
819                 return NULL;
820         }
821
822         for (; (next = ast_channel_iterator_next(iter)); ast_channel_unref(next)) {
823                 if (!strncmp(ast_channel_name(next), "DAHDI/pseudo", pseudo_len)
824                         || next == chan) {
825                         continue;
826                 }
827
828                 autochan_store = ast_autochan_setup(next);
829                 ast_channel_unref(next);
830
831                 return autochan_store;
832         }
833         return NULL;
834 }
835
836 static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
837         int volfactor, const int fd, struct spy_dtmf_options *user_options,
838         const char *mygroup, const char *myenforced, const char *spec, const char *exten,
839         const char *context, const char *mailbox, const char *name_context)
840 {
841         char nameprefix[AST_NAME_STRLEN];
842         char exitcontext[AST_MAX_CONTEXT] = "";
843         signed char zero_volume = 0;
844         int waitms;
845         int res;
846         int num_spyed_upon = 1;
847         struct ast_channel_iterator *iter = NULL;
848
849         if (ast_test_flag(flags, OPTION_EXIT)) {
850                 const char *c;
851                 ast_channel_lock(chan);
852                 if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) {
853                         ast_copy_string(exitcontext, c, sizeof(exitcontext));
854                 } else if (!ast_strlen_zero(ast_channel_macrocontext(chan))) {
855                         ast_copy_string(exitcontext, ast_channel_macrocontext(chan), sizeof(exitcontext));
856                 } else {
857                         ast_copy_string(exitcontext, ast_channel_context(chan), sizeof(exitcontext));
858                 }
859                 ast_channel_unlock(chan);
860         }
861
862         if (ast_channel_state(chan) != AST_STATE_UP)
863                 ast_answer(chan);
864
865         ast_set_flag(ast_channel_flags(chan), AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
866
867         waitms = 100;
868
869         for (;;) {
870                 struct ast_autochan *autochan = NULL, *next_autochan = NULL;
871                 struct ast_channel *prev = NULL;
872
873                 if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
874                         res = ast_streamfile(chan, "beep", ast_channel_language(chan));
875                         if (!res)
876                                 res = ast_waitstream(chan, "");
877                         else if (res < 0) {
878                                 ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
879                                 break;
880                         }
881                         if (!ast_strlen_zero(exitcontext)) {
882                                 char tmp[2];
883                                 tmp[0] = res;
884                                 tmp[1] = '\0';
885                                 if (!ast_goto_if_exists(chan, exitcontext, tmp, 1))
886                                         goto exit;
887                                 else
888                                         ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
889                         }
890                 }
891
892                 /* Set up the iterator we'll be using during this call */
893                 if (!ast_strlen_zero(spec)) {
894                         if (ast_test_flag(flags, OPTION_UNIQUEID)) {
895                                 struct ast_channel *unique_chan;
896
897                                 unique_chan = ast_channel_get_by_name(spec);
898                                 if (!unique_chan) {
899                                         res = -1;
900                                         goto exit;
901                                 }
902                                 iter = ast_channel_iterator_by_name_new(ast_channel_name(unique_chan), 0);
903                                 ast_channel_unref(unique_chan);
904                         } else {
905                                 iter = ast_channel_iterator_by_name_new(spec, strlen(spec));
906                         }
907                 } else if (!ast_strlen_zero(exten)) {
908                         iter = ast_channel_iterator_by_exten_new(exten, context);
909                 } else {
910                         iter = ast_channel_iterator_all_new();
911                 }
912
913                 if (!iter) {
914                         res = -1;
915                         goto exit;
916                 }
917
918                 res = ast_waitfordigit(chan, waitms);
919                 if (res < 0) {
920                         iter = ast_channel_iterator_destroy(iter);
921                         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
922                         break;
923                 }
924                 if (!ast_strlen_zero(exitcontext)) {
925                         char tmp[2];
926                         tmp[0] = res;
927                         tmp[1] = '\0';
928                         if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) {
929                                 iter = ast_channel_iterator_destroy(iter);
930                                 goto exit;
931                         } else {
932                                 ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext);
933                         }
934                 }
935
936                 /* reset for the next loop around, unless overridden later */
937                 waitms = 100;
938                 num_spyed_upon = 0;
939
940                 for (autochan = next_channel(iter, autochan, chan);
941                      autochan;
942                          prev = autochan->chan, ast_autochan_destroy(autochan),
943                      autochan = next_autochan ? next_autochan : 
944                                 next_channel(iter, autochan, chan), next_autochan = NULL) {
945                         int igrp = !mygroup;
946                         int ienf = !myenforced;
947
948                         if (autochan->chan == prev) {
949                                 ast_autochan_destroy(autochan);
950                                 break;
951                         }
952
953                         if (ast_check_hangup(chan)) {
954                                 ast_autochan_destroy(autochan);
955                                 break;
956                         }
957
958                         if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_channel_is_bridged(autochan->chan)) {
959                                 continue;
960                         }
961
962                         if (ast_check_hangup(autochan->chan) || ast_test_flag(ast_channel_flags(autochan->chan), AST_FLAG_SPYING)) {
963                                 continue;
964                         }
965
966                         if (mygroup) {
967                                 int num_groups = 0;
968                                 int num_mygroups = 0;
969                                 char dup_group[512];
970                                 char dup_mygroup[512];
971                                 char *groups[NUM_SPYGROUPS];
972                                 char *mygroups[NUM_SPYGROUPS];
973                                 const char *group = NULL;
974                                 int x;
975                                 int y;
976                                 ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup));
977                                 num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups,
978                                         ARRAY_LEN(mygroups));
979
980                                 /* Before dahdi scan was part of chanspy, it would use the "GROUP" variable 
981                                  * rather than "SPYGROUP", this check is done to preserve expected behavior */
982                                 if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) {
983                                         group = pbx_builtin_getvar_helper(autochan->chan, "GROUP");
984                                 } else {
985                                         group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP");
986                                 }
987
988                                 if (!ast_strlen_zero(group)) {
989                                         ast_copy_string(dup_group, group, sizeof(dup_group));
990                                         num_groups = ast_app_separate_args(dup_group, ':', groups,
991                                                 ARRAY_LEN(groups));
992                                 }
993
994                                 for (y = 0; y < num_mygroups; y++) {
995                                         for (x = 0; x < num_groups; x++) {
996                                                 if (!strcmp(mygroups[y], groups[x])) {
997                                                         igrp = 1;
998                                                         break;
999                                                 }
1000                                         }
1001                                 }
1002                         }
1003
1004                         if (!igrp) {
1005                                 continue;
1006                         }
1007                         if (myenforced) {
1008                                 char ext[AST_CHANNEL_NAME + 3];
1009                                 char buffer[512];
1010                                 char *end;
1011
1012                                 snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced);
1013
1014                                 ast_copy_string(ext + 1, ast_channel_name(autochan->chan), sizeof(ext) - 1);
1015                                 if ((end = strchr(ext, '-'))) {
1016                                         *end++ = ':';
1017                                         *end = '\0';
1018                                 }
1019
1020                                 ext[0] = ':';
1021
1022                                 if (strcasestr(buffer, ext)) {
1023                                         ienf = 1;
1024                                 }
1025                         }
1026
1027                         if (!ienf) {
1028                                 continue;
1029                         }
1030
1031                         if (!ast_test_flag(flags, OPTION_QUIET)) {
1032                                 char peer_name[AST_NAME_STRLEN + 5];
1033                                 char *ptr, *s;
1034
1035                                 strcpy(peer_name, "spy-");
1036                                 strncat(peer_name, ast_channel_name(autochan->chan), AST_NAME_STRLEN - 4 - 1);
1037                                 if ((ptr = strchr(peer_name, '/'))) {
1038                                         *ptr++ = '\0';
1039                                         for (s = peer_name; s < ptr; s++) {
1040                                                 *s = tolower(*s);
1041                                         }
1042                                         if ((s = strchr(ptr, '-'))) {
1043                                                 *s = '\0';
1044                                         }
1045                                 }
1046
1047                                 if (ast_test_flag(flags, OPTION_NAME)) {
1048                                         const char *local_context = S_OR(name_context, "default");
1049                                         const char *local_mailbox = S_OR(mailbox, ptr);
1050                                         if (local_mailbox) {
1051                                                 res = ast_app_sayname(chan, local_mailbox, local_context);
1052                                         } else {
1053                                                 res = -1;
1054                                         }
1055                                 }
1056                                 if (!ast_test_flag(flags, OPTION_NAME) || res < 0) {
1057                                         int num;
1058                                         if (!ast_test_flag(flags, OPTION_NOTECH)) {
1059                                                 if (ast_fileexists(peer_name, NULL, NULL) > 0) {
1060                                                         res = ast_streamfile(chan, peer_name, ast_channel_language(chan));
1061                                                         if (!res) {
1062                                                                 res = ast_waitstream(chan, "");
1063                                                         }
1064                                                         if (res) {
1065                                                                 ast_autochan_destroy(autochan);
1066                                                                 break;
1067                                                         }
1068                                                 } else {
1069                                                         res = ast_say_character_str(chan, peer_name, "", ast_channel_language(chan), AST_SAY_CASE_NONE);
1070                                                 }
1071                                         }
1072                                         if (ptr && (num = atoi(ptr))) {
1073                                                 ast_say_digits(chan, num, "", ast_channel_language(chan));
1074                                         }
1075                                 }
1076                         }
1077
1078                         res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
1079                         num_spyed_upon++;
1080
1081                         if (res == -1) {
1082                                 ast_autochan_destroy(autochan);
1083                                 iter = ast_channel_iterator_destroy(iter);
1084                                 goto exit;
1085                         } else if (res == -2) {
1086                                 res = 0;
1087                                 ast_autochan_destroy(autochan);
1088                                 iter = ast_channel_iterator_destroy(iter);
1089                                 goto exit;
1090                         } else if (res > 1 && spec && !ast_test_flag(flags, OPTION_UNIQUEID)) {
1091                                 struct ast_channel *next;
1092
1093                                 snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
1094
1095                                 if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) {
1096                                         next_autochan = ast_autochan_setup(next);
1097                                         next = ast_channel_unref(next);
1098                                 } else {
1099                                         /* stay on this channel, if it is still valid */
1100                                         if (!ast_check_hangup(autochan->chan)) {
1101                                                 next_autochan = ast_autochan_setup(autochan->chan);
1102                                         } else {
1103                                                 /* the channel is gone */
1104                                                 next_autochan = NULL;
1105                                         }
1106                                 }
1107                         } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) {
1108                                 ast_autochan_destroy(autochan);
1109                                 iter = ast_channel_iterator_destroy(iter);
1110                                 goto exit;
1111                         }
1112                 }
1113
1114                 iter = ast_channel_iterator_destroy(iter);
1115
1116                 if (res == -1 || ast_check_hangup(chan))
1117                         break;
1118                 if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) {
1119                         break;
1120                 }
1121         }
1122 exit:
1123
1124         ast_clear_flag(ast_channel_flags(chan), AST_FLAG_SPYING);
1125
1126         ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
1127
1128         return res;
1129 }
1130
1131 static int chanspy_exec(struct ast_channel *chan, const char *data)
1132 {
1133         char *myenforced = NULL;
1134         char *mygroup = NULL;
1135         char *recbase = NULL;
1136         int fd = 0;
1137         struct ast_flags flags;
1138         struct spy_dtmf_options user_options = {
1139                 .cycle = '*',
1140                 .volume = '#',
1141                 .exit = '\0',
1142         };
1143         struct ast_format oldwf;
1144         int volfactor = 0;
1145         int res;
1146         char *mailbox = NULL;
1147         char *name_context = NULL;
1148         AST_DECLARE_APP_ARGS(args,
1149                 AST_APP_ARG(spec);
1150                 AST_APP_ARG(options);
1151         );
1152         char *opts[OPT_ARG_ARRAY_SIZE];
1153         char *parse = ast_strdupa(data);
1154
1155         AST_STANDARD_APP_ARGS(args, parse);
1156         ast_format_clear(&oldwf);
1157
1158         if (args.spec && !strcmp(args.spec, "all"))
1159                 args.spec = NULL;
1160
1161         if (args.options) {
1162                 char tmp;
1163                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1164                 if (ast_test_flag(&flags, OPTION_GROUP))
1165                         mygroup = opts[OPT_ARG_GROUP];
1166
1167                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1168                         !(recbase = opts[OPT_ARG_RECORD]))
1169                         recbase = "chanspy";
1170
1171                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1172                         tmp = opts[OPT_ARG_EXIT][0];
1173                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1174                                 user_options.exit = tmp;
1175                         } else {
1176                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1177                         }
1178                 }
1179
1180                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1181                         tmp = opts[OPT_ARG_CYCLE][0];
1182                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1183                                 user_options.cycle = tmp;
1184                         } else {
1185                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1186                         }
1187                 }
1188
1189                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1190                         int vol;
1191
1192                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1193                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1194                         else
1195                                 volfactor = vol;
1196                 }
1197
1198                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1199                         ast_set_flag(&flags, OPTION_WHISPER);
1200
1201                 if (ast_test_flag(&flags, OPTION_ENFORCED))
1202                         myenforced = opts[OPT_ARG_ENFORCED];
1203
1204                 if (ast_test_flag(&flags, OPTION_NAME)) {
1205                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1206                                 char *delimiter;
1207                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1208                                         mailbox = opts[OPT_ARG_NAME];
1209                                         *delimiter++ = '\0';
1210                                         name_context = delimiter;
1211                                 } else {
1212                                         mailbox = opts[OPT_ARG_NAME];
1213                                 }
1214                         }
1215                 }
1216         } else {
1217                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1218         }
1219
1220         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1221         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1222                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1223                 return -1;
1224         }
1225
1226         if (recbase) {
1227                 char filename[PATH_MAX];
1228
1229                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1230                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1231                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1232                         fd = 0;
1233                 }
1234         }
1235
1236         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, myenforced, args.spec, NULL, NULL, mailbox, name_context);
1237
1238         if (fd)
1239                 close(fd);
1240
1241         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1242                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1243
1244         if (ast_test_flag(&flags, OPTION_EXITONHANGUP)) {
1245                 ast_verb(3, "Stopped spying due to the spied-on channel hanging up.\n");
1246         }
1247
1248         return res;
1249 }
1250
1251 static int extenspy_exec(struct ast_channel *chan, const char *data)
1252 {
1253         char *ptr, *exten = NULL;
1254         char *mygroup = NULL;
1255         char *recbase = NULL;
1256         int fd = 0;
1257         struct ast_flags flags;
1258         struct spy_dtmf_options user_options = {
1259                 .cycle = '*',
1260                 .volume = '#',
1261                 .exit = '\0',
1262         };
1263         struct ast_format oldwf;
1264         int volfactor = 0;
1265         int res;
1266         char *mailbox = NULL;
1267         char *name_context = NULL;
1268         AST_DECLARE_APP_ARGS(args,
1269                 AST_APP_ARG(context);
1270                 AST_APP_ARG(options);
1271         );
1272         char *parse = ast_strdupa(data);
1273
1274         AST_STANDARD_APP_ARGS(args, parse);
1275         ast_format_clear(&oldwf);
1276
1277         if (!ast_strlen_zero(args.context) && (ptr = strchr(args.context, '@'))) {
1278                 exten = args.context;
1279                 *ptr++ = '\0';
1280                 args.context = ptr;
1281         }
1282         if (ast_strlen_zero(args.context))
1283                 args.context = ast_strdupa(ast_channel_context(chan));
1284
1285         if (args.options) {
1286                 char *opts[OPT_ARG_ARRAY_SIZE];
1287                 char tmp;
1288
1289                 ast_app_parse_options(spy_opts, &flags, opts, args.options);
1290                 if (ast_test_flag(&flags, OPTION_GROUP))
1291                         mygroup = opts[OPT_ARG_GROUP];
1292
1293                 if (ast_test_flag(&flags, OPTION_RECORD) &&
1294                         !(recbase = opts[OPT_ARG_RECORD]))
1295                         recbase = "chanspy";
1296
1297                 if (ast_test_flag(&flags, OPTION_DTMF_EXIT) && opts[OPT_ARG_EXIT]) {
1298                         tmp = opts[OPT_ARG_EXIT][0];
1299                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1300                                 user_options.exit = tmp;
1301                         } else {
1302                                 ast_log(LOG_NOTICE, "Argument for option 'x' must be a valid DTMF digit.\n");
1303                         }
1304                 }
1305
1306                 if (ast_test_flag(&flags, OPTION_DTMF_CYCLE) && opts[OPT_ARG_CYCLE]) {
1307                         tmp = opts[OPT_ARG_CYCLE][0];
1308                         if (strchr("0123456789*#", tmp) && tmp != '\0') {
1309                                 user_options.cycle = tmp;
1310                         } else {
1311                                 ast_log(LOG_NOTICE, "Argument for option 'c' must be a valid DTMF digit.\n");
1312                         }
1313                 }
1314
1315                 if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
1316                         int vol;
1317
1318                         if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
1319                                 ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
1320                         else
1321                                 volfactor = vol;
1322                 }
1323
1324                 if (ast_test_flag(&flags, OPTION_PRIVATE))
1325                         ast_set_flag(&flags, OPTION_WHISPER);
1326
1327                 if (ast_test_flag(&flags, OPTION_NAME)) {
1328                         if (!ast_strlen_zero(opts[OPT_ARG_NAME])) {
1329                                 char *delimiter;
1330                                 if ((delimiter = strchr(opts[OPT_ARG_NAME], '@'))) {
1331                                         mailbox = opts[OPT_ARG_NAME];
1332                                         *delimiter++ = '\0';
1333                                         name_context = delimiter;
1334                                 } else {
1335                                         mailbox = opts[OPT_ARG_NAME];
1336                                 }
1337                         }
1338                 }
1339
1340         } else {
1341                 /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1342                 ast_clear_flag(&flags, AST_FLAGS_ALL);
1343         }
1344
1345         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1346         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1347                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1348                 return -1;
1349         }
1350
1351         if (recbase) {
1352                 char filename[PATH_MAX];
1353
1354                 snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
1355                 if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, AST_FILE_MODE)) <= 0) {
1356                         ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
1357                         fd = 0;
1358                 }
1359         }
1360
1361
1362         res = common_exec(chan, &flags, volfactor, fd, &user_options, mygroup, NULL, NULL, exten, args.context, mailbox, name_context);
1363
1364         if (fd)
1365                 close(fd);
1366
1367         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1368                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1369
1370         return res;
1371 }
1372
1373 static int dahdiscan_exec(struct ast_channel *chan, const char *data)
1374 {
1375         const char *spec = "DAHDI";
1376         struct ast_flags flags;
1377         struct spy_dtmf_options user_options = {
1378                 .cycle = '#',
1379                 .volume = '\0',
1380                 .exit = '*',
1381         };
1382         struct ast_format oldwf;
1383         int res;
1384         char *mygroup = NULL;
1385
1386         /* Coverity - This uninit_use should be ignored since this macro initializes the flags */
1387         ast_clear_flag(&flags, AST_FLAGS_ALL);
1388         ast_format_clear(&oldwf);
1389         if (!ast_strlen_zero(data)) {
1390                 mygroup = ast_strdupa(data);
1391         }
1392         ast_set_flag(&flags, OPTION_DTMF_EXIT);
1393         ast_set_flag(&flags, OPTION_DTMF_CYCLE);
1394         ast_set_flag(&flags, OPTION_DAHDI_SCAN);
1395
1396         ast_format_copy(&oldwf, ast_channel_writeformat(chan));
1397         if (ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR) < 0) {
1398                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1399                 return -1;
1400         }
1401
1402         res = common_exec(chan, &flags, 0, 0, &user_options, mygroup, NULL, spec, NULL, NULL, NULL, NULL);
1403
1404         if (oldwf.id && ast_set_write_format(chan, &oldwf) < 0)
1405                 ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
1406
1407         return res;
1408 }
1409
1410 static int unload_module(void)
1411 {
1412         int res = 0;
1413
1414         res |= ast_unregister_application(app_chan);
1415         res |= ast_unregister_application(app_ext);
1416         res |= ast_unregister_application(app_dahdiscan);
1417
1418         return res;
1419 }
1420
1421 static int load_module(void)
1422 {
1423         int res = 0;
1424
1425         res |= ast_register_application_xml(app_chan, chanspy_exec);
1426         res |= ast_register_application_xml(app_ext, extenspy_exec);
1427         res |= ast_register_application_xml(app_dahdiscan, dahdiscan_exec);
1428
1429         return res;
1430 }
1431
1432 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");