Asterisk - The Open Source Telephony Project GIT-master-f36a736
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, struct ast_config *ucfg, 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, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int search_directory_sub (const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, 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 162 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 164 of file app_directory.c.

164 {
165 OPT_LISTBYFIRSTNAME = (1 << 0),
166 OPT_SAYEXTENSION = (1 << 1),
167 OPT_FROMVOICEMAIL = (1 << 2),
168 OPT_SELECTFROMMENU = (1 << 3),
169 OPT_LISTBYLASTNAME = (1 << 4),
171 OPT_PAUSE = (1 << 5),
172 OPT_NOANSWER = (1 << 6),
173 OPT_ALIAS = (1 << 7),
174 OPT_CONFIG_FILE = (1 << 8),
175 OPT_SKIP = (1 << 9),
176 OPT_ADSI = (1 << 10),
177};
@ 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 179 of file app_directory.c.

179 {
182 OPT_ARG_EITHER = 2,
183 OPT_ARG_PAUSE = 3,
185 /* This *must* be the last value in this enum! */
187};
@ 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 552 of file app_directory.c.

555{

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1102 of file app_directory.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1102 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 235 of file app_directory.c.

236{
237 unsigned char buf[4096];
239 char *lines[5] = {NULL, NULL, NULL, NULL, NULL};
240 int x, bytes = 0;
241 unsigned char keys[8];
242 char matchbuf[32];
243
244 snprintf(matchbuf, sizeof(matchbuf), "%d of %d", seq + 1, total); /* Make it 1-indexed for user consumption */
245
246 lines[0] = " "; /* Leave the first line empty so the following lines stand out more */
247 lines[1] = matchbuf;
248 lines[2] = (char*) name;
249
250 if (showexten) {
251 /* If say extension option is set, show it for ADSI as well */
252 lines[3] = (char*) exten;
253 }
254
255 /* Don't use ast_adsi_print here, this way we can send it all at once instead of in 2 transmissions */
256 for (x = 0; lines[x]; x++) {
257 bytes += ast_adsi_display(buf + bytes, ADSI_INFO_PAGE, x + 1, alignments[x], 0, lines[x], "");
258 }
259 bytes += ast_adsi_set_line(buf + bytes, ADSI_INFO_PAGE, 1);
260
261 keys[3] = ADSI_KEY_APPS + 3;
262 keys[4] = ADSI_KEY_APPS + 4;
263 keys[5] = ADSI_KEY_APPS + 5;
264 /* You might think we only need to set the keys up the first time, but nope, we've got to do it each time. */
265 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Dial", "Dial", "1", 0);
266 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Next", "Next", "*", 0);
267 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 0);
268 bytes += ast_adsi_set_keys(buf + bytes, keys);
269 bytes += ast_adsi_voice_mode(buf + bytes, 0);
270
271 ast_debug(3, "Sending ADSI confirmation menu for %s\n", name);
272
273 return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
274}
#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:120
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 213 of file app_directory.c.

214{
215 unsigned char buf[256];
216 int bytes = 0;
217 unsigned char keys[6];
218
219 memset(keys, 0, sizeof(keys));
220
221 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
222 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
223 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
224 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Query: ***", "");
225 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
226 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Search", "Search", "#", 1);
227 bytes += ast_adsi_set_keys(buf + bytes, keys);
228 bytes += ast_adsi_voice_mode(buf + bytes, 0);
229
230 ast_debug(3, "Sending ADSI search input screen on %s\n", ast_channel_name(chan));
231
232 return ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
233}
#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 1102 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 652 of file app_directory.c.

653{
654 struct directory_item *item;
655 const char *key = NULL;
656 int namelen;
657
658 if (ast_strlen_zero(item_fullname)) {
659 return 0;
660 }
661
662 /* Set key to last name or first name depending on search mode */
663 if (!use_first_name)
664 key = strchr(item_fullname, ' ');
665
666 if (key)
667 key++;
668 else
669 key = item_fullname;
670
671 if (compare(key, pattern_ext))
672 return 0;
673
674 ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
675
676 /* Match */
677 item = ast_calloc(1, sizeof(*item));
678 if (!item)
679 return -1;
680 ast_copy_string(item->context, item_context, sizeof(item->context));
681 ast_copy_string(item->name, item_fullname, sizeof(item->name));
682 ast_copy_string(item->exten, item_ext, sizeof(item->exten));
683
684 ast_copy_string(item->key, key, sizeof(item->key));
685 if (key != item_fullname) {
686 /* Key is the last name. Append first name to key in order to sort Last,First */
687 namelen = key - item_fullname - 1;
688 if (namelen > sizeof(item->key) - strlen(item->key) - 1)
689 namelen = sizeof(item->key) - strlen(item->key) - 1;
690 strncat(item->key, item_fullname, namelen);
691 }
692
693 *result = item;
694 return 1;
695}
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 276 of file app_directory.c.

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

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 940 of file app_directory.c.

941{
942 int res = 0, digit = 3;
943 struct ast_config *cfg, *ucfg;
944 const char *dirintro;
945 char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, };
946 struct ast_flags flags = { 0 };
947 struct ast_flags config_flags = { 0 };
948 enum { FIRST, LAST, BOTH } which = LAST;
949 char digits[9] = "digits/3";
951 AST_APP_ARG(vmcontext);
954 );
955
956 parse = ast_strdupa(data);
957
959
960 if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
961 return -1;
962
964
965 if (!cfg) {
966 ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
967 return -1;
968 }
969
970 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
971 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
972 ucfg = NULL;
973 }
974
975 dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
976 if (ast_strlen_zero(dirintro))
977 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
978 /* the above prompts probably should be modified to include 0 for dialing operator
979 and # for exiting (continues in dialplan) */
980
982 if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) {
983 digit = atoi(opts[OPT_ARG_EITHER]);
984 }
985 which = BOTH;
988 digit = atoi(opts[OPT_ARG_FIRSTNAME]);
989 }
990 which = FIRST;
991 } else {
992 if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) {
993 digit = atoi(opts[OPT_ARG_LASTNAME]);
994 }
995 which = LAST;
996 }
997
998 /* If no options specified, search by last name */
1001 which = LAST;
1002 }
1003
1004 if (digit > 9) {
1005 digit = 9;
1006 } else if (digit < 1) {
1007 digit = 3;
1008 }
1009 digits[7] = digit + '0';
1010
1011 if (ast_test_flag(&flags, OPT_ADSI)) {
1012 if (!ast_adsi_available(chan)) {
1013 ast_log(LOG_WARNING, "ADSI not available on %s\n", ast_channel_name(chan));
1015 } else {
1016 res = ast_adsi_load_session(chan, NULL, 0, 1);
1017 if (res < 0) {
1018 return res;
1019 }
1020 }
1021 }
1022
1023 if (ast_channel_state(chan) != AST_STATE_UP) {
1025 /* Otherwise answer unless we're supposed to read while on-hook */
1026 res = ast_answer(chan);
1027 }
1028 }
1029 for (;;) {
1031 return -1;
1032 }
1033 if (!ast_strlen_zero(dirintro) && !res) {
1034 res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
1035 } else if (!res) {
1036 /* Stop playing sounds as soon as we have a digit. */
1037 res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY);
1038 if (!res) {
1039 res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY);
1040 }
1041 if (!res) {
1042 res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY);
1043 }
1044 if (!res) {
1045 res = ast_stream_and_wait(chan,
1046 which == FIRST ? "dir-first" :
1047 which == LAST ? "dir-last" :
1048 "dir-firstlast", AST_DIGIT_ANY);
1049 }
1050 if (!res) {
1051 res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY);
1052 }
1053 }
1054 ast_stopstream(chan);
1055 if (!res)
1056 res = ast_waitfordigit(chan, 5000);
1057
1058 if (res <= 0) {
1059 if (res == 0) {
1060 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "TIMEOUT");
1061 }
1062 break;
1063 }
1064
1065 res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts);
1066 if (res)
1067 break;
1068
1069 res = ast_waitstream(chan, AST_DIGIT_ANY);
1070 ast_stopstream(chan);
1071 if (res < 0) {
1072 break;
1073 }
1074 }
1075
1076 if (ucfg)
1077 ast_config_destroy(ucfg);
1078 ast_config_destroy(cfg);
1079
1080 if (ast_check_hangup(chan)) {
1081 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "HANGUP");
1082 } else if (res < 0) {
1083 /* If the res < 0 and we didn't hangup, an unaccounted for error must have happened. */
1084 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "FAILED");
1085 }
1086
1087 return res < 0 ? -1 : 0;
1088}
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 int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags, char *opts[])
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 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:3194
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:2824
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:1878
#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:1840
#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
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEINVALID
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:784
#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:199
unsigned int flags
Definition: utils.h:200
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_config_load, 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(), CONFIG_STATUS_FILEINVALID, 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,
struct ast_config ucfg,
char *  context,
char *  dialcontext,
char  digit,
int  digits,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 861 of file app_directory.c.

862{
863 /* Read in the first three digits.. "digit" is the first digit, already read */
864 int res = 0;
866 struct directory_item *item, **ptr, **sorted = NULL;
867 int count, i;
868 char ext[10] = "";
869
870 if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
871 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
872 return digit;
873 }
874
875 if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
876 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "ASSISTANT");
877 return digit;
878 }
879
880 ext[0] = digit;
881 if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0)
882 return -1;
883
884 res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist);
885 if (res)
886 goto exit;
887
888 /* Count items in the list */
889 count = 0;
891 count++;
892 }
893
894 if (count < 1) {
895 res = ast_streamfile(chan, "dir-nomatch", ast_channel_language(chan));
896 goto exit;
897 }
898
899
900 /* Create plain array of pointers to items (for sorting) */
901 sorted = ast_calloc(count, sizeof(*sorted));
902
903 ptr = sorted;
905 *ptr++ = item;
906 }
907
908 /* Sort items */
909 sort_items(sorted, count);
910
911 if (DEBUG_ATLEAST(2)) {
912 ast_log(LOG_DEBUG, "Listing matching entries:\n");
913 for (ptr = sorted, i = 0; i < count; i++, ptr++) {
914 ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
915 }
916 }
917
918 if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
919 /* Offer multiple entries at the same time */
920 res = select_item_menu(chan, sorted, count, dialcontext, flags, opts);
921 } else {
922 /* Offer entries one by one */
923 res = select_item_seq(chan, sorted, count, dialcontext, flags, opts);
924 }
925
926 if (!res) {
927 res = ast_streamfile(chan, "dir-nomore", ast_channel_language(chan));
928 }
929
930exit:
931 if (sorted)
932 ast_free(sorted);
933
934 while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
935 ast_free(item);
936
937 return res;
938}
static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
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 search_directory(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
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:6577
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1293
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
char exten[AST_MAX_EXTENSION+1]
Definition: search.h:40

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, 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 356 of file app_directory.c.

357{
359 return 0;
360 } else {
361 ast_log(LOG_WARNING, "Can't find extension '%s' in current context. "
362 "Not Exiting the Directory!\n", ext);
363 return -1;
364 }
365}
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:8781

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 1097 of file app_directory.c.

1098{
1100}
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 372 of file app_directory.c.

374{
375 int res = 0;
376 char *mailbox_id;
377
378 mailbox_id = ast_alloca(strlen(ext) + strlen(context) + 2);
379 sprintf(mailbox_id, "%s@%s", ext, context); /* Safe */
380
381 res = ast_app_sayname(chan, mailbox_id);
382 if (res >= 0) {
383 ast_stopstream(chan);
384 /* If Option 'e' was specified, also read the extension number with the name */
385 if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
386 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
388 }
389 } else {
392 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
394 }
395 }
396
397 return res;
398}
#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:8293
@ 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 554 of file app_directory.c.

555{
556 struct ast_config *cfg;
557 struct ast_config *rtdata = NULL;
558 struct ast_category *cat;
559 struct ast_variable *var;
560 char *category = NULL;
561 const char *fullname;
562 const char *hidefromdir, *searchcontexts = NULL;
563 struct ast_flags config_flags = { 0 };
564 struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
565
566 if (!tmp) {
567 return NULL;
568 }
569
570 /* Load flat file config. */
571 cfg = ast_config_load(filename, config_flags);
572
573 if (!cfg) {
574 /* Loading config failed. */
575 ast_log(LOG_WARNING, "Loading config failed.\n");
576 return NULL;
577 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
578 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", filename);
579 return NULL;
580 }
581
582 /* Get realtime entries, categorized by their mailbox number
583 and present in the requested context */
584 if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) {
585 if (ast_true(searchcontexts)) {
586 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL);
587 context = NULL;
588 } else {
589 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL);
590 context = "default";
591 }
592 } else if (!ast_strlen_zero(context)) {
593 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
594 }
595
596 /* if there are no results, just return the entries from the config file */
597 if (!rtdata) {
598 return cfg;
599 }
600
601 while ((category = ast_category_browse(rtdata, category))) {
602 const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox");
603 const char *ctx = ast_variable_retrieve(rtdata, category, "context");
604
606 ast_debug(3, "Skipping result with missing or empty mailbox\n");
607 continue;
608 }
609
610 fullname = ast_variable_retrieve(rtdata, category, "fullname");
611 hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir");
612 if (ast_true(hidefromdir)) {
613 /* Skip hidden */
614 continue;
615 }
616
617 /* password,Full Name,email,pager,options */
618 ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, ""));
619 if (ast_variable_retrieve(rtdata, category, "alias")) {
620 struct ast_variable *alias;
621 for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) {
622 if (!strcasecmp(alias->name, "alias")) {
623 ast_str_append(&tmp, 0, "|alias=%s", alias->value);
624 }
625 }
626 }
627
628 /* Does the context exist within the config file? If not, make one */
629 if (!(cat = ast_category_get(cfg, ctx, NULL))) {
630 if (!(cat = ast_category_new_dynamic(ctx))) {
631 ast_log(LOG_WARNING, "Out of memory\n");
633 if (rtdata) {
634 ast_config_destroy(rtdata);
635 }
636 return NULL;
637 }
638 ast_category_append(cfg, cat);
639 }
640
643 } else {
644 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
645 }
646 }
647 ast_config_destroy(rtdata);
648
649 return cfg;
650}
#define var
Definition: ast_expr2f.c:605
static int tmp()
Definition: bt_open.c:389
#define SENTINEL
Definition: compiler.h:87
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:3637
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 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:1120
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, tmp(), ast_variable::value, and var.

Referenced by directory_exec().

◆ search_directory()

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

Definition at line 810 of file app_directory.c.

811{
812 const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts");
814 if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) {
815 /* Browse each context for a match */
816 int res;
817 const char *catg;
818 for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) {
819 if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) {
820 continue;
821 }
822
823 if ((res = search_directory_sub(catg, vmcfg, ucfg, ext, flags, alist))) {
824 return res;
825 }
826 }
827 return 0;
828 } else {
829 ast_debug(1, "Searching by category default\n");
830 return search_directory_sub("default", vmcfg, ucfg, ext, flags, alist);
831 }
832 } else {
833 /* Browse only the listed context for a match */
834 ast_debug(1, "Searching by category %s\n", context);
835 return search_directory_sub(context, vmcfg, ucfg, ext, flags, alist);
836 }
837}
static int search_directory_sub(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, 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,
struct ast_config ucfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 699 of file app_directory.c.

700{
701 struct ast_variable *v;
702 struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
703 char *name;
704 char *options;
705 char *alias;
706 char *cat;
707 struct directory_item *item;
708 int res;
709
710 if (!buf) {
711 return -1;
712 }
713
714 ast_debug(2, "Pattern: %s\n", ext);
715
716 for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
717 ast_str_set(&buf, 0, "%s", v->value);
719
720 /* password,Full Name,email,pager,options */
721 strsep(&options, ","); /* Skip password */
722 name = strsep(&options, ","); /* Save full name */
723 strsep(&options, ","); /* Skip email */
724 strsep(&options, ","); /* Skip pager */
725 /* options is now the options field if it exists. */
726
727 if (options && strcasestr(options, "hidefromdir=yes")) {
728 /* Ignore hidden */
729 continue;
730 }
731 if (ast_strlen_zero(name)) {
732 /* No name to compare against */
733 continue;
734 }
735
736 res = 0;
737 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
738 res = check_match(&item, context, name, v->name, ext, 0 /* use_first_name */);
739 }
740 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
741 res = check_match(&item, context, name, v->name, ext, 1 /* use_first_name */);
742 }
743 if (!res && ast_test_flag(&flags, OPT_ALIAS)
744 && options && (alias = strcasestr(options, "alias="))) {
745 char *a;
746
747 ast_debug(1, "Found alias: %s\n", alias);
748 while ((a = strsep(&alias, "|"))) {
749 if (!strncasecmp(a, "alias=", 6)) {
750 if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
751 break;
752 }
753 }
754 }
755 }
756
757 if (!res) {
758 continue;
759 } else if (res < 0) {
760 return -1;
761 }
762
764 }
765
766 if (ucfg) {
767 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
768 const char *position;
769
770 if (!strcasecmp(cat, "general")) {
771 continue;
772 }
773 if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) {
774 continue;
775 }
776
777 /* Find all candidate extensions */
778 if (!(position = ast_variable_retrieve(ucfg, cat, "fullname"))) {
779 continue;
780 }
781
782 res = 0;
783 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
784 res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */);
785 }
786 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
787 res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
788 }
789 if (!res && ast_test_flag(&flags, OPT_ALIAS)) {
790 for (v = ast_variable_browse(ucfg, cat); v; v = v->next) {
791 if (!strcasecmp(v->name, "alias")
792 && (res = check_match(&item, context, v->value, cat, ext, 1))) {
793 break;
794 }
795 }
796 }
797
798 if (!res) {
799 continue;
800 } else if (res < 0) {
801 return -1;
802 }
803
805 }
806 }
807 return 0;
808}
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 *)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
Definition: main/config.c:774
#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_category_browse(), ast_config_option(), ast_debug, AST_LIST_INSERT_TAIL, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero(), ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), voicemailpwcheck::context, ext, item, name, ast_variable::name, ast_variable::next, NULL, 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 400 of file app_directory.c.

401{
402 ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context));
403
404 if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
405 /* We still want to set the exten though */
406 ast_channel_exten_set(chan, item->exten);
407 } else if (ast_test_flag(flags, OPT_SKIP)) {
408 /* Skip calling the extension, only set it in the channel variable. */
409 pbx_builtin_setvar_helper(chan, "DIRECTORY_EXTEN", item->exten);
410 } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) {
412 "Can't find extension '%s' in context '%s'. "
413 "Did you pass the wrong context to Directory?\n",
414 item->exten, S_OR(dialcontext, item->context));
415 return -1;
416 }
417
418 pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
419 return 0;
420}
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 488 of file app_directory.c.

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

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

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 436 of file app_directory.c.

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

840{
841 int reordered, i;
842 struct directory_item **ptr, *tmp;
843
844 if (count < 2)
845 return;
846
847 /* Bubble-sort items by the key */
848 do {
849 reordered = 0;
850 for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
851 if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
852 tmp = ptr[0];
853 ptr[0] = ptr[1];
854 ptr[1] = tmp;
855 reordered++;
856 }
857 }
858 } while (reordered);
859}

References directory_item::key, and tmp().

Referenced by do_directory().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1090 of file app_directory.c.

1091{
1092 int res;
1094 return res;
1095}
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 1102 of file app_directory.c.

◆ app

const char app[] = "Directory"
static

Definition at line 157 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 1102 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 552 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 211 of file app_directory.c.

Referenced by directory_exec().