Asterisk - The Open Source Telephony Project GIT-master-43bf8a4
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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 __init_commonbuf (void)
 
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)
 
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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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 struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
 
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

◆ __init_commonbuf()

static void __init_commonbuf ( void  )
static

Definition at line 555 of file app_directory.c.

558{

◆ __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.

◆ 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
Definition: test_config.c:1463

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
char * text
Definition: app_queue.c:1809

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:3143
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:444
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
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:1886
#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:1848
#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:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:869
#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.
#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:217
unsigned int flags
Definition: utils.h:218
const char * args
static struct test_options options
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

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:6513
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1301
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.
Definition: linkedlists.h:491
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:252
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
Definition: f2c.h:129
struct directory_item::@19 entry
char exten[AST_MAX_EXTENSION+1]

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, voicemailpwcheck::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:8272
@ 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, voicemailpwcheck::context, 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
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:3326
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3854
void ast_category_append(struct ast_config *config, struct ast_category *category)
Appends a category to a config.
Definition: extconf.c:2833
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1177
#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:1215
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1205
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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
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:2199
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
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
Definition: term.c:57

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, voicemailpwcheck::context, LOG_ERROR, LOG_WARNING, voicemailpwcheck::mailbox, 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");
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(), voicemailpwcheck::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.
Definition: linkedlists.h:731
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(), voicemailpwcheck::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 = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .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.

◆ commonbuf

struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
static

Definition at line 555 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().