Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
app_directory.c File Reference

Provide a directory of extensions. More...

#include "asterisk.h"
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/adsi.h"
Include dependency graph for app_directory.c:

Go to the source code of this file.

Data Structures

struct  directory_item
 
struct  itemlist
 

Macros

#define VOICEMAIL_CONFIG   "voicemail.conf"
 

Enumerations

enum  {
  OPT_LISTBYFIRSTNAME = (1 << 0) , OPT_SAYEXTENSION = (1 << 1) , OPT_FROMVOICEMAIL = (1 << 2) , OPT_SELECTFROMMENU = (1 << 3) ,
  OPT_LISTBYLASTNAME = (1 << 4) , OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME , OPT_PAUSE = (1 << 5) , OPT_NOANSWER = (1 << 6) ,
  OPT_ALIAS = (1 << 7) , OPT_CONFIG_FILE = (1 << 8) , OPT_SKIP = (1 << 9) , OPT_ADSI = (1 << 10)
}
 
enum  {
  OPT_ARG_FIRSTNAME = 0 , OPT_ARG_LASTNAME = 1 , OPT_ARG_EITHER = 2 , OPT_ARG_PAUSE = 3 ,
  OPT_ARG_FILENAME = 4 , OPT_ARG_ARRAY_SIZE = 5
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int adsi_confirm_match (struct ast_channel *chan, int seq, int total, const char *exten, const char *name, int showexten)
 
static int adsi_search_input (struct ast_channel *chan)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_THREADSTORAGE_CUSTOM_SCOPE (commonbuf, NULL, ast_free_ptr, static)
 
static int check_match (struct directory_item **result, const char *item_context, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name)
 
static int compare (const char *text, const char *template)
 
static int directory_exec (struct ast_channel *chan, const char *data)
 
static int do_directory (struct ast_channel *chan, struct ast_config *vmcfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags, char *opts[])
 
static int goto_exten (struct ast_channel *chan, const char *dialcontext, char *ext)
 
static int load_module (void)
 
static int play_mailbox_owner (struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)
 
static struct ast_configrealtime_directory (char *context, const char *filename)
 
static int search_directory (const char *context, struct ast_config *vmcfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int search_directory_sub (const char *context, struct ast_config *vmcfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int select_entry (struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
 
static int select_item_menu (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static int select_item_pause (struct ast_channel *chan, struct ast_flags *flags, char *opts[])
 
static int select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static void sort_items (struct directory_item **sorted, int count)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "Directory"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option directory_app_options [128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, [ 'c' ] = { .flag = OPT_CONFIG_FILE , .arg_index = OPT_ARG_FILENAME + 1 }, [ 's' ] = { .flag = OPT_SKIP }, [ 'd' ] = { .flag = OPT_ADSI }, }
 

Detailed Description

Provide a directory of extensions.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_directory.c.

Macro Definition Documentation

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 165 of file app_directory.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_LISTBYFIRSTNAME 
OPT_SAYEXTENSION 
OPT_FROMVOICEMAIL 
OPT_SELECTFROMMENU 
OPT_LISTBYLASTNAME 
OPT_LISTBYEITHER 
OPT_PAUSE 
OPT_NOANSWER 
OPT_ALIAS 
OPT_CONFIG_FILE 
OPT_SKIP 
OPT_ADSI 

Definition at line 167 of file app_directory.c.

167 {
168 OPT_LISTBYFIRSTNAME = (1 << 0),
169 OPT_SAYEXTENSION = (1 << 1),
170 OPT_FROMVOICEMAIL = (1 << 2),
171 OPT_SELECTFROMMENU = (1 << 3),
172 OPT_LISTBYLASTNAME = (1 << 4),
174 OPT_PAUSE = (1 << 5),
175 OPT_NOANSWER = (1 << 6),
176 OPT_ALIAS = (1 << 7),
177 OPT_CONFIG_FILE = (1 << 8),
178 OPT_SKIP = (1 << 9),
179 OPT_ADSI = (1 << 10),
180};
@ OPT_LISTBYFIRSTNAME
@ OPT_LISTBYEITHER
@ OPT_NOANSWER
@ OPT_LISTBYLASTNAME
@ OPT_CONFIG_FILE
@ OPT_SKIP
@ OPT_SAYEXTENSION
@ OPT_ALIAS
@ OPT_SELECTFROMMENU
@ OPT_PAUSE
@ OPT_FROMVOICEMAIL
@ OPT_ADSI

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_FIRSTNAME 
OPT_ARG_LASTNAME 
OPT_ARG_EITHER 
OPT_ARG_PAUSE 
OPT_ARG_FILENAME 
OPT_ARG_ARRAY_SIZE 

Definition at line 182 of file app_directory.c.

182 {
185 OPT_ARG_EITHER = 2,
186 OPT_ARG_PAUSE = 3,
188 /* This *must* be the last value in this enum! */
190};
@ OPT_ARG_LASTNAME
@ OPT_ARG_FIRSTNAME
@ OPT_ARG_FILENAME
@ OPT_ARG_PAUSE
@ OPT_ARG_ARRAY_SIZE
@ OPT_ARG_EITHER

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1054 of file app_directory.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1054 of file app_directory.c.

◆ adsi_confirm_match()

static int adsi_confirm_match ( struct ast_channel chan,
int  seq,
int  total,
const char *  exten,
const char *  name,
int  showexten 
)
static

Definition at line 238 of file app_directory.c.

239{
240 unsigned char buf[4096];
242 char *lines[5] = {NULL, NULL, NULL, NULL, NULL};
243 int x, bytes = 0;
244 unsigned char keys[8];
245 char matchbuf[32];
246
247 snprintf(matchbuf, sizeof(matchbuf), "%d of %d", seq + 1, total); /* Make it 1-indexed for user consumption */
248
249 lines[0] = " "; /* Leave the first line empty so the following lines stand out more */
250 lines[1] = matchbuf;
251 lines[2] = (char*) name;
252
253 if (showexten) {
254 /* If say extension option is set, show it for ADSI as well */
255 lines[3] = (char*) exten;
256 }
257
258 /* Don't use ast_adsi_print here, this way we can send it all at once instead of in 2 transmissions */
259 for (x = 0; lines[x]; x++) {
260 bytes += ast_adsi_display(buf + bytes, ADSI_INFO_PAGE, x + 1, alignments[x], 0, lines[x], "");
261 }
262 bytes += ast_adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
263
264 keys[3] = ADSI_KEY_APPS + 3;
265 keys[4] = ADSI_KEY_APPS + 4;
266 keys[5] = ADSI_KEY_APPS + 5;
267 /* You might think we only need to set the keys up the first time, but nope, we've got to do it each time. */
268 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Dial", "Dial", "1", 0);
269 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Next", "Next", "*", 0);
270 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 0);
271 bytes += ast_adsi_set_keys(buf + bytes, keys);
272 bytes += ast_adsi_voice_mode(buf + bytes, 0);
273
274 ast_debug(3, "Sending ADSI confirmation menu for %s\n", name);
275
276 return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
277}
#define ADSI_KEY_APPS
Definition adsi.h:109
int ast_adsi_display(unsigned char *buf, int page, int line, int just, int wrap, char *col1, char *col2)
Loads a line of info into the display.
Definition adsi.c:274
#define ADSI_INFO_PAGE
Definition adsi.h:106
int ast_adsi_load_soft_key(unsigned char *buf, int key, const char *llabel, const char *slabel, char *ret, int data)
Creates "load soft key" parameters.
Definition adsi.c:296
#define ADSI_JUST_CENT
Definition adsi.h:114
#define ADSI_MSG_DISPLAY
Definition adsi.h:32
int ast_adsi_set_line(unsigned char *buf, int page, int line)
Sets the current line and page.
Definition adsi.c:285
int ast_adsi_transmit_message(struct ast_channel *chan, unsigned char *msg, int msglen, int msgtype)
Definition adsi.c:98
int ast_adsi_set_keys(unsigned char *buf, unsigned char *keys)
Set which soft keys should be displayed.
Definition adsi.c:307
int ast_adsi_voice_mode(unsigned char *buf, int when)
Puts CPE in voice mode.
Definition adsi.c:252
static volatile unsigned int seq
Definition app_sms.c:126
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static const char name[]
Definition format_mp3.c:68
#define ast_debug(level,...)
Log a DEBUG message.
static int total
Definition res_adsi.c:970
#define NULL
Definition resample.c:96

References ADSI_INFO_PAGE, ADSI_JUST_CENT, ADSI_KEY_APPS, ADSI_MSG_DISPLAY, ast_adsi_display(), ast_adsi_load_soft_key(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_debug, buf, name, NULL, seq, and total.

Referenced by select_item_seq().

◆ adsi_search_input()

static int adsi_search_input ( struct ast_channel chan)
static

Definition at line 216 of file app_directory.c.

217{
218 unsigned char buf[256];
219 int bytes = 0;
220 unsigned char keys[6];
221
222 memset(keys, 0, sizeof(keys));
223
224 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
225 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
226 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
227 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Query: ***", "");
228 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
229 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Search", "Search", "#", 1);
230 bytes += ast_adsi_set_keys(buf + bytes, keys);
231 bytes += ast_adsi_voice_mode(buf + bytes, 0);
232
233 ast_debug(3, "Sending ADSI search input screen on %s\n", ast_channel_name(chan));
234
235 return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
236}
#define ADSI_JUST_LEFT
Definition adsi.h:112
#define ADSI_COMM_PAGE
Definition adsi.h:107
int ast_adsi_input_control(unsigned char *buf, int page, int line, int display, int format, int just)
Set input information.
Definition adsi.c:318
int ast_adsi_input_format(unsigned char *buf, int num, int dir, int wrap, char *format1, char *format2)
Set input format.
Definition adsi.c:329
#define ADSI_DIR_FROM_LEFT
Definition adsi.h:120
const char * ast_channel_name(const struct ast_channel *chan)

References ADSI_COMM_PAGE, ADSI_DIR_FROM_LEFT, ADSI_JUST_CENT, ADSI_JUST_LEFT, ADSI_KEY_APPS, ADSI_MSG_DISPLAY, ast_adsi_display(), ast_adsi_input_control(), ast_adsi_input_format(), ast_adsi_load_soft_key(), ast_adsi_set_keys(), ast_adsi_set_line(), ast_adsi_transmit_message(), ast_adsi_voice_mode(), ast_channel_name(), ast_debug, and buf.

Referenced by directory_exec().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1054 of file app_directory.c.

◆ AST_THREADSTORAGE_CUSTOM_SCOPE()

AST_THREADSTORAGE_CUSTOM_SCOPE ( commonbuf  ,
NULL  ,
ast_free_ptr  ,
static   
)

◆ check_match()

static int check_match ( struct directory_item **  result,
const char *  item_context,
const char *  item_fullname,
const char *  item_ext,
const char *  pattern_ext,
int  use_first_name 
)
static

Definition at line 655 of file app_directory.c.

656{
657 struct directory_item *item;
658 const char *key = NULL;
659 int namelen;
660
661 if (ast_strlen_zero(item_fullname)) {
662 return 0;
663 }
664
665 /* Set key to last name or first name depending on search mode */
666 if (!use_first_name)
667 key = strchr(item_fullname, ' ');
668
669 if (key)
670 key++;
671 else
672 key = item_fullname;
673
674 if (compare(key, pattern_ext))
675 return 0;
676
677 ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
678
679 /* Match */
680 item = ast_calloc(1, sizeof(*item));
681 if (!item)
682 return -1;
683 ast_copy_string(item->context, item_context, sizeof(item->context));
684 ast_copy_string(item->name, item_fullname, sizeof(item->name));
685 ast_copy_string(item->exten, item_ext, sizeof(item->exten));
686
687 ast_copy_string(item->key, key, sizeof(item->key));
688 if (key != item_fullname) {
689 /* Key is the last name. Append first name to key in order to sort Last,First */
690 namelen = key - item_fullname - 1;
691 if (namelen > sizeof(item->key) - strlen(item->key) - 1)
692 namelen = sizeof(item->key) - strlen(item->key) - 1;
693 strncat(item->key, item_fullname, namelen);
694 }
695
696 *result = item;
697 return 1;
698}
static int compare(const char *text, const char *template)
#define ast_calloc(num, len)
A wrapper for calloc()
Definition astmm.h:202
static PGresult * result
Definition cel_pgsql.c:84
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
const char * name
static struct aco_type item

References ast_calloc, ast_copy_string(), ast_debug, ast_strlen_zero(), compare(), item, directory_item::key, aco_type::name, NULL, and result.

Referenced by search_directory_sub().

◆ compare()

static int compare ( const char *  text,
const char *  template 
)
static

Definition at line 279 of file app_directory.c.

280{
281 char digit;
282
283 if (ast_strlen_zero(text)) {
284 return -1;
285 }
286
287 while (*template) {
288 digit = toupper(*text++);
289 switch (digit) {
290 case 0:
291 return -1;
292 case '1':
293 digit = '1';
294 break;
295 case '2':
296 case 'A':
297 case 'B':
298 case 'C':
299 digit = '2';
300 break;
301 case '3':
302 case 'D':
303 case 'E':
304 case 'F':
305 digit = '3';
306 break;
307 case '4':
308 case 'G':
309 case 'H':
310 case 'I':
311 digit = '4';
312 break;
313 case '5':
314 case 'J':
315 case 'K':
316 case 'L':
317 digit = '5';
318 break;
319 case '6':
320 case 'M':
321 case 'N':
322 case 'O':
323 digit = '6';
324 break;
325 case '7':
326 case 'P':
327 case 'Q':
328 case 'R':
329 case 'S':
330 digit = '7';
331 break;
332 case '8':
333 case 'T':
334 case 'U':
335 case 'V':
336 digit = '8';
337 break;
338 case '9':
339 case 'W':
340 case 'X':
341 case 'Y':
342 case 'Z':
343 digit = '9';
344 break;
345
346 default:
347 if (digit > ' ')
348 return -1;
349 continue;
350 }
351
352 if (*template++ != digit)
353 return -1;
354 }
355
356 return 0;
357}
char digit

References ast_strlen_zero(), digit, and text.

Referenced by _ast_hashtab_create(), ast_sip_is_content_type(), and check_match().

◆ directory_exec()

static int directory_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 900 of file app_directory.c.

901{
902 int res = 0, digit = 3;
903 struct ast_config *cfg;
904 const char *dirintro;
905 char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, };
906 struct ast_flags flags = { 0 };
907 enum { FIRST, LAST, BOTH } which = LAST;
908 char digits[9] = "digits/3";
910 AST_APP_ARG(vmcontext);
913 );
914
915 parse = ast_strdupa(data);
916
918
919 if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
920 return -1;
921
923
924 if (!cfg) {
925 ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
926 return -1;
927 }
928
929 dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
930 if (ast_strlen_zero(dirintro))
931 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
932 /* the above prompts probably should be modified to include 0 for dialing operator
933 and # for exiting (continues in dialplan) */
934
936 if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) {
937 digit = atoi(opts[OPT_ARG_EITHER]);
938 }
939 which = BOTH;
942 digit = atoi(opts[OPT_ARG_FIRSTNAME]);
943 }
944 which = FIRST;
945 } else {
946 if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) {
947 digit = atoi(opts[OPT_ARG_LASTNAME]);
948 }
949 which = LAST;
950 }
951
952 /* If no options specified, search by last name */
955 which = LAST;
956 }
957
958 if (digit > 9) {
959 digit = 9;
960 } else if (digit < 1) {
961 digit = 3;
962 }
963 digits[7] = digit + '0';
964
966 if (!ast_adsi_available(chan)) {
967 ast_log(LOG_WARNING, "ADSI not available on %s\n", ast_channel_name(chan));
969 } else {
970 res = ast_adsi_load_session(chan, NULL, 0, 1);
971 if (res < 0) {
972 return res;
973 }
974 }
975 }
976
977 if (ast_channel_state(chan) != AST_STATE_UP) {
979 /* Otherwise answer unless we're supposed to read while on-hook */
980 res = ast_answer(chan);
981 }
982 }
983 for (;;) {
985 return -1;
986 }
987 if (!ast_strlen_zero(dirintro) && !res) {
988 res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
989 } else if (!res) {
990 /* Stop playing sounds as soon as we have a digit. */
991 res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY);
992 if (!res) {
993 res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY);
994 }
995 if (!res) {
996 res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY);
997 }
998 if (!res) {
999 res = ast_stream_and_wait(chan,
1000 which == FIRST ? "dir-first" :
1001 which == LAST ? "dir-last" :
1002 "dir-firstlast", AST_DIGIT_ANY);
1003 }
1004 if (!res) {
1005 res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY);
1006 }
1007 }
1008 ast_stopstream(chan);
1009 if (!res)
1010 res = ast_waitfordigit(chan, 5000);
1011
1012 if (res <= 0) {
1013 if (res == 0) {
1014 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "TIMEOUT");
1015 }
1016 break;
1017 }
1018
1019 res = do_directory(chan, cfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts);
1020 if (res)
1021 break;
1022
1023 res = ast_waitstream(chan, AST_DIGIT_ANY);
1024 ast_stopstream(chan);
1025 if (res < 0) {
1026 break;
1027 }
1028 }
1029
1030 ast_config_destroy(cfg);
1031
1032 if (ast_check_hangup(chan)) {
1033 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "HANGUP");
1034 } else if (res < 0) {
1035 /* If the res < 0 and we didn't hangup, an unaccounted for error must have happened. */
1036 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "FAILED");
1037 }
1038
1039 return res < 0 ? -1 : 0;
1040}
int ast_adsi_load_session(struct ast_channel *chan, unsigned char *app, int ver, int data)
Check if scripts for a given app are already loaded. Version may be -1, if any version is okay,...
Definition adsi.c:76
int ast_adsi_available(struct ast_channel *chan)
Returns non-zero if Channel does or might support ADSI.
Definition adsi.c:263
static const struct ast_app_option directory_app_options[128]
static struct ast_config * realtime_directory(char *context, const char *filename)
#define VOICEMAIL_CONFIG
static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags, char *opts[])
static int adsi_search_input(struct ast_channel *chan)
static char dialcontext[AST_MAX_CONTEXT]
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define ast_log
Definition astobj2.c:42
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition channel.c:3172
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition channel.c:445
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition channel.c:2803
ast_channel_state
ast_channel states
@ AST_STATE_UP
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition file.c:223
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition file.c:1912
#define AST_DIGIT_ANY
Definition file.h:48
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition file.c:1874
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition main/app.c:3066
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition extconf.c:1287
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
#define LOG_ERROR
#define LOG_WARNING
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
static struct @519 args
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition strings.h:80
Structure used to handle boolean flags.
Definition utils.h:220
unsigned int flags
Definition utils.h:221
static struct test_options options
#define ast_test_flag(p, flag)
Definition utils.h:64
#define ast_clear_flag(p, flag)
Definition utils.h:78
#define ast_set_flag(p, flag)
Definition utils.h:71

References adsi_search_input(), args, ast_adsi_available(), ast_adsi_load_session(), ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_channel_name(), ast_check_hangup(), ast_clear_flag, ast_config_destroy(), AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_log, ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), dialcontext, digit, directory_app_options, do_directory(), ast_flags::flags, LOG_ERROR, LOG_WARNING, NULL, OPT_ADSI, OPT_ARG_ARRAY_SIZE, OPT_ARG_EITHER, OPT_ARG_FILENAME, OPT_ARG_FIRSTNAME, OPT_ARG_LASTNAME, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, OPT_NOANSWER, options, pbx_builtin_setvar_helper(), realtime_directory(), S_OR, and VOICEMAIL_CONFIG.

Referenced by load_module().

◆ do_directory()

static int do_directory ( struct ast_channel chan,
struct ast_config vmcfg,
char *  context,
char *  dialcontext,
char  digit,
int  digits,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 821 of file app_directory.c.

822{
823 /* Read in the first three digits.. "digit" is the first digit, already read */
824 int res = 0;
826 struct directory_item *item, **ptr, **sorted = NULL;
827 int count, i;
828 char ext[10] = "";
829
830 if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
831 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
832 return digit;
833 }
834
835 if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
836 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "ASSISTANT");
837 return digit;
838 }
839
840 ext[0] = digit;
841 if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0)
842 return -1;
843
844 res = search_directory(context, vmcfg, ext, *flags, &alist);
845 if (res)
846 goto exit;
847
848 /* Count items in the list */
849 count = 0;
851 count++;
852 }
853
854 if (count < 1) {
855 res = ast_streamfile(chan, "dir-nomatch", ast_channel_language(chan));
856 goto exit;
857 }
858
859
860 /* Create plain array of pointers to items (for sorting) */
861 sorted = ast_calloc(count, sizeof(*sorted));
862
863 ptr = sorted;
865 *ptr++ = item;
866 }
867
868 /* Sort items */
869 sort_items(sorted, count);
870
871 if (DEBUG_ATLEAST(2)) {
872 ast_log(LOG_DEBUG, "Listing matching entries:\n");
873 for (ptr = sorted, i = 0; i < count; i++, ptr++) {
874 ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
875 }
876 }
877
878 if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
879 /* Offer multiple entries at the same time */
880 res = select_item_menu(chan, sorted, count, dialcontext, flags, opts);
881 } else {
882 /* Offer entries one by one */
883 res = select_item_seq(chan, sorted, count, dialcontext, flags, opts);
884 }
885
886 if (!res) {
887 res = ast_streamfile(chan, "dir-nomore", ast_channel_language(chan));
888 }
889
890exit:
891 if (sorted)
892 ast_free(sorted);
893
894 while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
895 ast_free(item);
896
897 return res;
898}
static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
static int search_directory(const char *context, struct ast_config *vmcfg, const char *ext, struct ast_flags flags, itemlist *alist)
static void sort_items(struct directory_item **sorted, int count)
static int select_item_menu(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
#define ast_free(a)
Definition astmm.h:180
const char * ast_channel_language(const struct ast_channel *chan)
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition channel.c:6553
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition file.c:1312
const char * ext
Definition http.c:150
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition f2c.h:129
char context[AST_MAX_CONTEXT+1]
char exten[AST_MAX_EXTENSION+1]
struct directory_item::@20 entry

References ast_calloc, ast_channel_language(), ast_free, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log, ast_readstring(), ast_streamfile(), ast_test_flag, directory_item::context, DEBUG_ATLEAST, dialcontext, digit, directory_item::entry, ext, directory_item::exten, goto_exten(), item, LOG_DEBUG, name, NULL, OPT_SELECTFROMMENU, pbx_builtin_setvar_helper(), search_directory(), select_item_menu(), select_item_seq(), and sort_items().

Referenced by directory_exec().

◆ goto_exten()

static int goto_exten ( struct ast_channel chan,
const char *  dialcontext,
char *  ext 
)
static

Definition at line 359 of file app_directory.c.

360{
362 return 0;
363 } else {
364 ast_log(LOG_WARNING, "Can't find extension '%s' in current context. "
365 "Not Exiting the Directory!\n", ext);
366 return -1;
367 }
368}
const char * ast_channel_context(const struct ast_channel *chan)
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition pbx.c:8806

References ast_channel_context(), ast_goto_if_exists(), ast_log, dialcontext, ext, LOG_WARNING, and S_OR.

Referenced by do_directory(), and select_item_seq().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1049 of file app_directory.c.

1050{
1052}
static const char app[]
static int directory_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition module.h:640

References app, ast_register_application_xml, and directory_exec().

◆ play_mailbox_owner()

static int play_mailbox_owner ( struct ast_channel chan,
const char *  context,
const char *  ext,
const char *  name,
struct ast_flags flags 
)
static

Definition at line 375 of file app_directory.c.

377{
378 int res = 0;
379 char *mailbox_id;
380
381 mailbox_id = ast_alloca(strlen(ext) + strlen(context) + 2);
382 sprintf(mailbox_id, "%s@%s", ext, context); /* Safe */
383
384 res = ast_app_sayname(chan, mailbox_id);
385 if (res >= 0) {
386 ast_stopstream(chan);
387 /* If Option 'e' was specified, also read the extension number with the name */
388 if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
389 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
391 }
392 } else {
395 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
397 }
398 }
399
400 return res;
401}
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition astmm.h:288
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
Play a recorded user name for the mailbox to the specified channel.
Definition main/app.c:637
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
Definition channel.c:8315
@ AST_SAY_CASE_NONE
Definition say.h:182

References ast_alloca, ast_app_sayname(), ast_channel_language(), AST_DIGIT_ANY, AST_SAY_CASE_NONE, ast_say_character_str(), ast_stopstream(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ext, name, OPT_SAYEXTENSION, and S_OR.

Referenced by select_item_menu(), and select_item_seq().

◆ realtime_directory()

static struct ast_config * realtime_directory ( char *  context,
const char *  filename 
)
static

Definition at line 557 of file app_directory.c.

558{
559 struct ast_config *cfg;
560 struct ast_config *rtdata = NULL;
561 struct ast_category *cat;
562 struct ast_variable *var;
563 char *category = NULL;
564 const char *fullname;
565 const char *hidefromdir, *searchcontexts = NULL;
566 struct ast_flags config_flags = { 0 };
567 struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
568
569 if (!tmp) {
570 return NULL;
571 }
572
573 /* Load flat file config. */
574 cfg = ast_config_load(filename, config_flags);
575
576 if (!cfg) {
577 /* Loading config failed. */
578 ast_log(LOG_WARNING, "Loading config failed.\n");
579 return NULL;
580 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
581 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", filename);
582 return NULL;
583 }
584
585 /* Get realtime entries, categorized by their mailbox number
586 and present in the requested context */
587 if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) {
588 if (ast_true(searchcontexts)) {
589 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL);
590 context = NULL;
591 } else {
592 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL);
593 context = "default";
594 }
595 } else if (!ast_strlen_zero(context)) {
596 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
597 }
598
599 /* if there are no results, just return the entries from the config file */
600 if (!rtdata) {
601 return cfg;
602 }
603
604 while ((category = ast_category_browse(rtdata, category))) {
605 const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox");
606 const char *ctx = ast_variable_retrieve(rtdata, category, "context");
607
608 if (ast_strlen_zero(mailbox)) {
609 ast_debug(3, "Skipping result with missing or empty mailbox\n");
610 continue;
611 }
612
613 fullname = ast_variable_retrieve(rtdata, category, "fullname");
614 hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir");
615 if (ast_true(hidefromdir)) {
616 /* Skip hidden */
617 continue;
618 }
619
620 /* password,Full Name,email,pager,options */
621 ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, ""));
622 if (ast_variable_retrieve(rtdata, category, "alias")) {
623 struct ast_variable *alias;
624 for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) {
625 if (!strcasecmp(alias->name, "alias")) {
626 ast_str_append(&tmp, 0, "|alias=%s", alias->value);
627 }
628 }
629 }
630
631 /* Does the context exist within the config file? If not, make one */
632 if (!(cat = ast_category_get(cfg, ctx, NULL))) {
633 if (!(cat = ast_category_new_dynamic(ctx))) {
634 ast_log(LOG_WARNING, "Out of memory\n");
636 if (rtdata) {
637 ast_config_destroy(rtdata);
638 }
639 return NULL;
640 }
641 ast_category_append(cfg, cat);
642 }
643
644 if ((var = ast_variable_new(mailbox, ast_str_buffer(tmp), ""))) {
646 } else {
647 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
648 }
649 }
650 ast_config_destroy(rtdata);
651
652 return cfg;
653}
#define var
Definition ast_expr2f.c:605
#define SENTINEL
Definition compiler.h:87
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition extconf.c:3324
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition extconf.c:2831
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition extconf.c:1175
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEINVALID
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition extconf.c:1213
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition strings.h:1139
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition utils.c:2235
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition strings.h:1113
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition strings.h:761
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition strings.h:909
Support for dynamic strings.
Definition strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next

References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new_dynamic, ast_config_destroy(), ast_config_load, ast_debug, ast_load_realtime_multientry(), ast_log, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ast_true(), ast_variable_append(), ast_variable_browse(), ast_variable_new, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, LOG_WARNING, ast_variable::name, ast_variable::next, NULL, S_OR, SENTINEL, ast_variable::value, and var.

Referenced by directory_exec().

◆ search_directory()

static int search_directory ( const char *  context,
struct ast_config vmcfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 770 of file app_directory.c.

771{
772 const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts");
773 if (ast_strlen_zero(context)) {
774 if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) {
775 /* Browse each context for a match */
776 int res;
777 const char *catg;
778 for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) {
779 if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) {
780 continue;
781 }
782
783 if ((res = search_directory_sub(catg, vmcfg, ext, flags, alist))) {
784 return res;
785 }
786 }
787 return 0;
788 } else {
789 ast_debug(1, "Searching by category default\n");
790 return search_directory_sub("default", vmcfg, ext, flags, alist);
791 }
792 } else {
793 /* Browse only the listed context for a match */
794 ast_debug(1, "Searching by category %s\n", context);
795 return search_directory_sub(context, vmcfg, ext, flags, alist);
796 }
797}
static int search_directory_sub(const char *context, struct ast_config *vmcfg, const char *ext, struct ast_flags flags, itemlist *alist)

References ast_category_browse(), ast_debug, ast_strlen_zero(), ast_true(), ast_variable_retrieve(), directory_item::context, ext, NULL, and search_directory_sub().

Referenced by do_directory().

◆ search_directory_sub()

static int search_directory_sub ( const char *  context,
struct ast_config vmcfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 702 of file app_directory.c.

703{
704 struct ast_variable *v;
705 struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
706 char *name;
707 char *options;
708 char *alias;
709 struct directory_item *item;
710 int res;
711
712 if (!buf) {
713 return -1;
714 }
715
716 ast_debug(2, "Pattern: %s\n", ext);
717
718 for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
719 ast_str_set(&buf, 0, "%s", v->value);
721
722 /* password,Full Name,email,pager,options */
723 strsep(&options, ","); /* Skip password */
724 name = strsep(&options, ","); /* Save full name */
725 strsep(&options, ","); /* Skip email */
726 strsep(&options, ","); /* Skip pager */
727 /* options is now the options field if it exists. */
728
729 if (options && strcasestr(options, "hidefromdir=yes")) {
730 /* Ignore hidden */
731 continue;
732 }
733 if (ast_strlen_zero(name)) {
734 /* No name to compare against */
735 continue;
736 }
737
738 res = 0;
739 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
740 res = check_match(&item, context, name, v->name, ext, 0 /* use_first_name */);
741 }
742 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
743 res = check_match(&item, context, name, v->name, ext, 1 /* use_first_name */);
744 }
745 if (!res && ast_test_flag(&flags, OPT_ALIAS)
746 && options && (alias = strcasestr(options, "alias="))) {
747 char *a;
748
749 ast_debug(1, "Found alias: %s\n", alias);
750 while ((a = strsep(&alias, "|"))) {
751 if (!strncasecmp(a, "alias=", 6)) {
752 if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
753 break;
754 }
755 }
756 }
757 }
758
759 if (!res) {
760 continue;
761 } else if (res < 0) {
762 return -1;
763 }
764
766 }
767 return 0;
768}
static int check_match(struct directory_item **result, const char *item_context, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name)
char * strsep(char **str, const char *delims)
char * strcasestr(const char *, const char *)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
static struct test_val a

References a, ast_debug, AST_LIST_INSERT_TAIL, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ast_test_flag, ast_variable_browse(), buf, check_match(), directory_item::context, directory_item::entry, ext, item, name, ast_variable::name, ast_variable::next, OPT_ALIAS, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, options, strcasestr(), strsep(), and ast_variable::value.

Referenced by search_directory().

◆ select_entry()

static int select_entry ( struct ast_channel chan,
const char *  dialcontext,
const struct directory_item item,
struct ast_flags flags 
)
static

Definition at line 403 of file app_directory.c.

404{
405 ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context));
406
407 if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
408 /* We still want to set the exten though */
409 ast_channel_exten_set(chan, item->exten);
410 } else if (ast_test_flag(flags, OPT_SKIP)) {
411 /* Skip calling the extension, only set it in the channel variable. */
412 pbx_builtin_setvar_helper(chan, "DIRECTORY_EXTEN", item->exten);
413 } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) {
415 "Can't find extension '%s' in context '%s'. "
416 "Did you pass the wrong context to Directory?\n",
417 item->exten, S_OR(dialcontext, item->context));
418 return -1;
419 }
420
421 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
422 return 0;
423}
void ast_channel_exten_set(struct ast_channel *chan, const char *value)

References ast_channel_exten_set(), ast_debug, ast_goto_if_exists(), ast_log, ast_test_flag, dialcontext, item, LOG_WARNING, aco_type::name, OPT_FROMVOICEMAIL, OPT_SKIP, pbx_builtin_setvar_helper(), and S_OR.

Referenced by select_item_menu(), and select_item_seq().

◆ select_item_menu()

static int select_item_menu ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 491 of file app_directory.c.

492{
493 struct directory_item **block, *item;
494 int i, limit, res = 0;
495 char buf[7+12]; /* INT_MIN has a length of 12 chars */
496
497 /* option p(n): cellphone pause option */
498 select_item_pause(chan, flags, opts);
499
500 for (block = items; count; block += limit, count -= limit) {
501 limit = count;
502 if (limit > 8)
503 limit = 8;
504
505 for (i = 0; i < limit && !res; i++) {
506 item = block[i];
507
508 snprintf(buf, sizeof(buf), "digits/%d", i + 1);
509 /* Press <num> for <name>, [ extension <ext> ] */
510 res = ast_streamfile(chan, "dir-multi1", ast_channel_language(chan));
511 if (!res)
512 res = ast_waitstream(chan, AST_DIGIT_ANY);
513 if (!res)
514 res = ast_streamfile(chan, buf, ast_channel_language(chan));
515 if (!res)
516 res = ast_waitstream(chan, AST_DIGIT_ANY);
517 if (!res)
518 res = ast_streamfile(chan, "dir-multi2", ast_channel_language(chan));
519 if (!res)
520 res = ast_waitstream(chan, AST_DIGIT_ANY);
521 if (!res)
522 res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
523 if (!res)
524 res = ast_waitstream(chan, AST_DIGIT_ANY);
525 if (!res)
526 res = ast_waitfordigit(chan, 800);
527 }
528
529 /* Press "9" for more names. */
530 if (!res && count > limit) {
531 res = ast_streamfile(chan, "dir-multi9", ast_channel_language(chan));
532 if (!res)
533 res = ast_waitstream(chan, AST_DIGIT_ANY);
534 }
535
536 if (!res) {
537 res = ast_waitfordigit(chan, 3000);
538 }
539
540 if (res && res > '0' && res < '1' + limit) {
541 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
542 return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1;
543 }
544
545 if (res < 0)
546 return -1;
547
548 res = 0;
549 }
550
551 /* Nothing was selected */
552 return 0;
553}
static int select_item_pause(struct ast_channel *chan, struct ast_flags *flags, char *opts[])
static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
static int play_mailbox_owner(struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)

References ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, dialcontext, item, aco_type::name, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

◆ select_item_pause()

static int select_item_pause ( struct ast_channel chan,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 425 of file app_directory.c.

426{
427 int res = 0, opt_pause = 0;
428
429 if (ast_test_flag(flags, OPT_PAUSE) && !ast_strlen_zero(opts[OPT_ARG_PAUSE])) {
430 opt_pause = atoi(opts[OPT_ARG_PAUSE]);
431 if (opt_pause > 3000) {
432 opt_pause = 3000;
433 }
434 res = ast_waitfordigit(chan, opt_pause);
435 }
436 return res;
437}

References ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), OPT_ARG_PAUSE, and OPT_PAUSE.

Referenced by select_item_menu(), and select_item_seq().

◆ select_item_seq()

static int select_item_seq ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 439 of file app_directory.c.

440{
441 struct directory_item *item, **ptr;
442 int i, res, loop;
443
444 /* option p(n): cellphone pause option */
445 /* allow early press of selection key */
446 res = select_item_pause(chan, flags, opts);
447
448 for (ptr = items, i = 0; i < count; i++, ptr++) {
449 item = *ptr;
450
451 if (ast_test_flag(flags, OPT_ADSI) && adsi_confirm_match(chan, i, count, item->exten, item->name, ast_test_flag(flags, OPT_SAYEXTENSION))) {
452 return -1;
453 }
454
455 for (loop = 3 ; loop > 0; loop--) {
456 if (!res)
457 res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
458 if (!res)
459 res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
460 if (!res)
461 res = ast_waitfordigit(chan, 3000);
462 ast_stopstream(chan);
463
464 if (res == '0') { /* operator selected */
465 goto_exten(chan, dialcontext, "o");
466 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
467 return '0';
468 } else if (res == '1') { /* Name selected */
469 return select_entry(chan, dialcontext, item, flags) ? -1 : 1;
470 } else if (res == '*') {
471 /* Skip to next match in list */
472 break;
473 } else if (res == '#') {
474 /* Exit reading, continue in dialplan */
475 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "USEREXIT");
476 return res;
477 }
478
479 if (res < 0)
480 return -1;
481
482 res = 0;
483 }
484 res = 0;
485 }
486
487 /* Nothing was selected */
488 return 0;
489}
static int adsi_confirm_match(struct ast_channel *chan, int seq, int total, const char *exten, const char *name, int showexten)

References adsi_confirm_match(), AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_test_flag, ast_waitfordigit(), dialcontext, goto_exten(), item, aco_type::name, OPT_ADSI, OPT_SAYEXTENSION, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

◆ sort_items()

static void sort_items ( struct directory_item **  sorted,
int  count 
)
static

Definition at line 799 of file app_directory.c.

800{
801 int reordered, i;
802 struct directory_item **ptr, *tmp;
803
804 if (count < 2)
805 return;
806
807 /* Bubble-sort items by the key */
808 do {
809 reordered = 0;
810 for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
811 if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
812 tmp = ptr[0];
813 ptr[0] = ptr[1];
814 ptr[1] = tmp;
815 reordered++;
816 }
817 }
818 } while (reordered);
819}

References directory_item::key.

Referenced by do_directory().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1042 of file app_directory.c.

1043{
1044 int res;
1046 return res;
1047}
int ast_unregister_application(const char *app)
Unregister an application.
Definition pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 1054 of file app_directory.c.

◆ app

const char app[] = "Directory"
static

Definition at line 160 of file app_directory.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1054 of file app_directory.c.

◆ directory_app_options

const struct ast_app_option directory_app_options[128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, [ 'c' ] = { .flag = OPT_CONFIG_FILE , .arg_index = OPT_ARG_FILENAME + 1 }, [ 's' ] = { .flag = OPT_SKIP }, [ 'd' ] = { .flag = OPT_ADSI }, }
static

Definition at line 214 of file app_directory.c.

Referenced by directory_exec().