Pay attention to the searchcontexts entry in voicemail.conf (related to AST-125)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@152727 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.2
Tilghman Lesher 17 years ago
parent fa06ce2e6c
commit 77060afdac

@ -33,6 +33,9 @@ Applications
using MeetMeAdmin. using MeetMeAdmin.
* app_authenticate now gives the ability to select a prompt other than * app_authenticate now gives the ability to select a prompt other than
the default. the default.
* app_directory now pays attention to the searchcontexts setting in
voicemail.conf and will look through all contexts, if no context is
specified in the initial argument.
Miscellaneous Miscellaneous
------------- -------------

@ -46,7 +46,7 @@ static char *app = "Directory";
static char *synopsis = "Provide directory of voicemail extensions"; static char *synopsis = "Provide directory of voicemail extensions";
static char *descrip = static char *descrip =
" Directory(vm-context[,dial-context[,options]]): This application will present\n" " Directory([vm-context][,dial-context[,options]]): This application will present\n"
"the calling channel with a directory of extensions from which they can search\n" "the calling channel with a directory of extensions from which they can search\n"
"by name. The list of names and corresponding extensions is retrieved from the\n" "by name. The list of names and corresponding extensions is retrieved from the\n"
"voicemail configuration file, voicemail.conf.\n" "voicemail configuration file, voicemail.conf.\n"
@ -56,7 +56,9 @@ static char *descrip =
" * - Jump to the 'a' extension, if it exists.\n\n" " * - Jump to the 'a' extension, if it exists.\n\n"
" Parameters:\n" " Parameters:\n"
" vm-context - This is the context within voicemail.conf to use for the\n" " vm-context - This is the context within voicemail.conf to use for the\n"
" Directory.\n" " Directory. If not specified and searchcontexts=no in\n"
" voicemail.conf, then \"default\" will be assumed.\n"
" Otherwise, in not specified, all contexts will be searched.\n"
" dial-context - This is the dialplan context to use when looking for an\n" " dial-context - This is the dialplan context to use when looking for an\n"
" extension that the user has selected, or when jumping to the\n" " extension that the user has selected, or when jumping to the\n"
" 'o' or 'a' extension.\n\n" " 'o' or 'a' extension.\n\n"
@ -112,6 +114,7 @@ enum {
struct directory_item { struct directory_item {
char exten[AST_MAX_EXTENSION + 1]; char exten[AST_MAX_EXTENSION + 1];
char name[AST_MAX_EXTENSION + 1]; char name[AST_MAX_EXTENSION + 1];
char context[AST_MAX_CONTEXT + 1];
char key[50]; /* Text to order items. Either lastname+firstname or firstname+lastname */ char key[50]; /* Text to order items. Either lastname+firstname or firstname+lastname */
AST_LIST_ENTRY(directory_item) entry; AST_LIST_ENTRY(directory_item) entry;
@ -234,25 +237,25 @@ static int play_mailbox_owner(struct ast_channel *chan, const char *context,
return res; return res;
} }
static int select_entry(struct ast_channel *chan, const char *context, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags) static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
{ {
ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, dialcontext); ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context));
if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) { if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
/* We still want to set the exten though */ /* We still want to set the exten though */
ast_copy_string(chan->exten, item->exten, sizeof(chan->exten)); ast_copy_string(chan->exten, item->exten, sizeof(chan->exten));
} else if (ast_goto_if_exists(chan, dialcontext, item->exten, 1)) { } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) {
ast_log(LOG_WARNING, ast_log(LOG_WARNING,
"Can't find extension '%s' in context '%s'. " "Can't find extension '%s' in context '%s'. "
"Did you pass the wrong context to Directory?\n", "Did you pass the wrong context to Directory?\n",
item->exten, dialcontext); item->exten, S_OR(dialcontext, item->context));
return -1; return -1;
} }
return 0; return 0;
} }
static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *context, const char *dialcontext, struct ast_flags *flags) static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags)
{ {
struct directory_item *item, **ptr; struct directory_item *item, **ptr;
int i, res, loop; int i, res, loop;
@ -261,7 +264,7 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
item = *ptr; item = *ptr;
for (loop = 3 ; loop > 0; loop--) { for (loop = 3 ; loop > 0; loop--) {
res = play_mailbox_owner(chan, context, item->exten, item->name, flags); res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
if (!res) if (!res)
res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY); res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
@ -270,7 +273,7 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
ast_stopstream(chan); ast_stopstream(chan);
if (res == '1') { /* Name selected */ if (res == '1') { /* Name selected */
return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1; return select_entry(chan, dialcontext, item, flags) ? -1 : 1;
} else if (res == '*') { } else if (res == '*') {
/* Skip to next match in list */ /* Skip to next match in list */
break; break;
@ -287,7 +290,7 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
return 0; return 0;
} }
static int select_item_menu(struct ast_channel *chan, struct directory_item **items, int count, const char *context, const char *dialcontext, 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)
{ {
struct directory_item **block, *item; struct directory_item **block, *item;
int i, limit, res = 0; int i, limit, res = 0;
@ -315,7 +318,7 @@ static int select_item_menu(struct ast_channel *chan, struct directory_item **it
if (!res) if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY); res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!res) if (!res)
res = play_mailbox_owner(chan, context, item->exten, item->name, flags); res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
if (!res) if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY); res = ast_waitstream(chan, AST_DIGIT_ANY);
if (!res) if (!res)
@ -334,7 +337,7 @@ static int select_item_menu(struct ast_channel *chan, struct directory_item **it
} }
if (res && res > '0' && res < '1' + limit) { if (res && res > '0' && res < '1' + limit) {
return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1; return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1;
} }
if (res < 0) if (res < 0)
@ -355,7 +358,7 @@ static struct ast_config *realtime_directory(char *context)
struct ast_variable *var; struct ast_variable *var;
char *mailbox; char *mailbox;
const char *fullname; const char *fullname;
const char *hidefromdir; const char *hidefromdir, *searchcontexts = NULL;
char tmp[100]; char tmp[100];
struct ast_flags config_flags = { 0 }; struct ast_flags config_flags = { 0 };
@ -373,49 +376,64 @@ static struct ast_config *realtime_directory(char *context)
/* Get realtime entries, categorized by their mailbox number /* Get realtime entries, categorized by their mailbox number
and present in the requested context */ and present in the requested context */
rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL); if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) {
if (ast_true(searchcontexts)) {
rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL);
context = NULL;
} else {
rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL);
context = "default";
}
} else {
rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
}
/* if there are no results, just return the entries from the config file */ /* if there are no results, just return the entries from the config file */
if (!rtdata) if (!rtdata) {
return cfg; return cfg;
/* Does the context exist within the config file? If not, make one */
cat = ast_category_get(cfg, context);
if (!cat) {
cat = ast_category_new(context, "", 99999);
if (!cat) {
ast_log(LOG_WARNING, "Out of memory\n");
ast_config_destroy(cfg);
return NULL;
}
ast_category_append(cfg, cat);
} }
mailbox = NULL; mailbox = NULL;
while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
const char *context = ast_variable_retrieve(rtdata, mailbox, "context");
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) { if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) {
/* Skip hidden */ /* Skip hidden */
continue; continue;
} }
snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, "")); snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, ""));
var = ast_variable_new(mailbox, tmp, "");
if (var) /* Does the context exist within the config file? If not, make one */
if (!(cat = ast_category_get(cfg, context))) {
if (!(cat = ast_category_new(context, "", 99999))) {
ast_log(LOG_WARNING, "Out of memory\n");
ast_config_destroy(cfg);
return NULL;
}
ast_category_append(cfg, cat);
}
if ((var = ast_variable_new(mailbox, tmp, ""))) {
ast_variable_append(cat, var); ast_variable_append(cat, var);
else } else {
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
}
} }
ast_config_destroy(rtdata); ast_config_destroy(rtdata);
return cfg; return cfg;
} }
static int check_match(struct directory_item **result, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name) 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)
{ {
struct directory_item *item; struct directory_item *item;
const char *key = NULL; const char *key = NULL;
int namelen; int namelen;
if (ast_strlen_zero(item_fullname)) {
return 0;
}
/* Set key to last name or first name depending on search mode */ /* Set key to last name or first name depending on search mode */
if (!use_first_name) if (!use_first_name)
@ -429,10 +447,13 @@ static int check_match(struct directory_item **result, const char *item_fullname
if (compare(key, pattern_ext)) if (compare(key, pattern_ext))
return 0; return 0;
ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
/* Match */ /* Match */
item = ast_calloc(1, sizeof(*item)); item = ast_calloc(1, sizeof(*item));
if (!item) if (!item)
return -1; return -1;
ast_copy_string(item->context, item_context, sizeof(item->context));
ast_copy_string(item->name, item_fullname, sizeof(item->name)); ast_copy_string(item->name, item_fullname, sizeof(item->name));
ast_copy_string(item->exten, item_ext, sizeof(item->exten)); ast_copy_string(item->exten, item_ext, sizeof(item->exten));
@ -451,7 +472,7 @@ static int check_match(struct directory_item **result, const char *item_fullname
typedef AST_LIST_HEAD_NOLOCK(, directory_item) itemlist; typedef AST_LIST_HEAD_NOLOCK(, directory_item) itemlist;
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)
{ {
struct ast_variable *v; struct ast_variable *v;
char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat; char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
@ -475,10 +496,10 @@ static int search_directory(const char *context, struct ast_config *vmcfg, struc
res = 0; res = 0;
if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
res = check_match(&item, pos, v->name, ext, 0 /* use_first_name */); res = check_match(&item, context, pos, v->name, ext, 0 /* use_first_name */);
} }
if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
res = check_match(&item, pos, v->name, ext, 1 /* use_first_name */); res = check_match(&item, context, pos, v->name, ext, 1 /* use_first_name */);
} }
if (!res) if (!res)
@ -504,10 +525,10 @@ static int search_directory(const char *context, struct ast_config *vmcfg, struc
res = 0; res = 0;
if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
res = check_match(&item, position, cat, ext, 0 /* use_first_name */); res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */);
} }
if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
res = check_match(&item, position, cat, ext, 1 /* use_first_name */); res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
} }
if (!res) if (!res)
@ -521,6 +542,35 @@ static int search_directory(const char *context, struct ast_config *vmcfg, struc
return 0; return 0;
} }
static int search_directory(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
{
const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts");
if (ast_strlen_zero(context)) {
if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) {
/* Browse each context for a match */
int res;
const char *catg;
for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) {
if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) {
continue;
}
if ((res = search_directory_sub(catg, vmcfg, ucfg, ext, flags, alist))) {
return res;
}
}
return 0;
} else {
ast_debug(1, "Searching by category default\n");
return search_directory_sub("default", vmcfg, ucfg, ext, flags, alist);
}
} else {
/* Browse only the listed context for a match */
ast_debug(1, "Searching by category %s\n", context);
return search_directory_sub(context, vmcfg, ucfg, ext, flags, alist);
}
}
static void sort_items(struct directory_item **sorted, int count) static void sort_items(struct directory_item **sorted, int count)
{ {
int reordered, i; int reordered, i;
@ -565,18 +615,11 @@ static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, stru
int count, i; int count, i;
char ext[10] = ""; char ext[10] = "";
if (ast_strlen_zero(context)) { if (digit == '0' && !goto_exten(chan, S_OR(dialcontext, "default"), "o")) {
ast_log(LOG_WARNING,
"Directory must be called with an argument "
"(context in which to interpret extensions)\n");
return -1;
}
if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
return 0; return 0;
} }
if (digit == '*' && !goto_exten(chan, dialcontext, "a")) { if (digit == '*' && !goto_exten(chan, S_OR(dialcontext, "default"), "a")) {
return 0; return 0;
} }
@ -614,16 +657,16 @@ static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, stru
if (option_debug) { if (option_debug) {
ast_debug(2, "Listing matching entries:\n"); ast_debug(2, "Listing matching entries:\n");
for (ptr = sorted, i = 0; i < count; i++, ptr++) { for (ptr = sorted, i = 0; i < count; i++, ptr++) {
ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name); ast_debug(2, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
} }
} }
if (ast_test_flag(flags, OPT_SELECTFROMMENU)) { if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
/* Offer multiple entries at the same time */ /* Offer multiple entries at the same time */
res = select_item_menu(chan, sorted, count, context, dialcontext, flags); res = select_item_menu(chan, sorted, count, dialcontext, flags);
} else { } else {
/* Offer entries one by one */ /* Offer entries one by one */
res = select_item_seq(chan, sorted, count, context, dialcontext, flags); res = select_item_seq(chan, sorted, count, dialcontext, flags);
} }
if (!res) { if (!res) {
@ -645,7 +688,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
int res = 0, digit = 3; int res = 0, digit = 3;
struct ast_config *cfg, *ucfg; struct ast_config *cfg, *ucfg;
const char *dirintro; const char *dirintro;
char *parse, *opts[OPT_ARG_ARRAY_SIZE]; char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, };
struct ast_flags flags = { 0 }; struct ast_flags flags = { 0 };
struct ast_flags config_flags = { 0 }; struct ast_flags config_flags = { 0 };
enum { FIRST, LAST, BOTH } which = LAST; enum { FIRST, LAST, BOTH } which = LAST;
@ -656,11 +699,6 @@ static int directory_exec(struct ast_channel *chan, void *data)
AST_APP_ARG(options); AST_APP_ARG(options);
); );
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
return -1;
}
parse = ast_strdupa(data); parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse); AST_STANDARD_APP_ARGS(args, parse);
@ -668,11 +706,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options)) if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
return -1; return -1;
if (ast_strlen_zero(args.dialcontext)) if (!(cfg = realtime_directory(args.vmcontext))) {
args.dialcontext = args.vmcontext;
cfg = realtime_directory(args.vmcontext);
if (!cfg) {
ast_log(LOG_ERROR, "Unable to read the configuration data!\n"); ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
return -1; return -1;
} }

Loading…
Cancel
Save