aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_directory.c
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-30 02:08:02 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-10-30 02:08:02 +0000
commit565e1cd62bcdcabc2b9145f4006ef654ae26b733 (patch)
tree6ae212c09023c7df237668c9c72e74f0a2a310b0 /apps/app_directory.c
parentf138e9dbd084701facb87acf46a3de231be869bc (diff)
Pay attention to the searchcontexts entry in voicemail.conf (related to AST-125)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@152727 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_directory.c')
-rw-r--r--apps/app_directory.c150
1 files changed, 92 insertions, 58 deletions
diff --git a/apps/app_directory.c b/apps/app_directory.c
index 30b8f7f46..b2a5741ed 100644
--- a/apps/app_directory.c
+++ b/apps/app_directory.c
@@ -46,7 +46,7 @@ static char *app = "Directory";
static char *synopsis = "Provide directory of voicemail extensions";
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"
"by name. The list of names and corresponding extensions is retrieved from the\n"
"voicemail configuration file, voicemail.conf.\n"
@@ -56,7 +56,9 @@ static char *descrip =
" * - Jump to the 'a' extension, if it exists.\n\n"
" Parameters:\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"
" extension that the user has selected, or when jumping to the\n"
" 'o' or 'a' extension.\n\n"
@@ -112,6 +114,7 @@ enum {
struct directory_item {
char exten[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 */
AST_LIST_ENTRY(directory_item) entry;
@@ -234,25 +237,25 @@ static int play_mailbox_owner(struct ast_channel *chan, const char *context,
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)) {
/* We still want to set the exten though */
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,
"Can't find extension '%s' in context '%s'. "
"Did you pass the wrong context to Directory?\n",
- item->exten, dialcontext);
+ item->exten, S_OR(dialcontext, item->context));
return -1;
}
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;
int i, res, loop;
@@ -261,7 +264,7 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
item = *ptr;
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)
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);
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 == '*') {
/* Skip to next match in list */
break;
@@ -287,7 +290,7 @@ static int select_item_seq(struct ast_channel *chan, struct directory_item **ite
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;
int i, limit, res = 0;
@@ -315,7 +318,7 @@ static int select_item_menu(struct ast_channel *chan, struct directory_item **it
if (!res)
res = ast_waitstream(chan, AST_DIGIT_ANY);
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)
res = ast_waitstream(chan, AST_DIGIT_ANY);
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) {
- 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)
@@ -355,7 +358,7 @@ static struct ast_config *realtime_directory(char *context)
struct ast_variable *var;
char *mailbox;
const char *fullname;
- const char *hidefromdir;
+ const char *hidefromdir, *searchcontexts = NULL;
char tmp[100];
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
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 (!rtdata)
+ if (!rtdata) {
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;
while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
+ const char *context = ast_variable_retrieve(rtdata, mailbox, "context");
+
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) {
/* Skip hidden */
continue;
}
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);
- else
+ } else {
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
+ }
}
ast_config_destroy(rtdata);
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;
const char *key = NULL;
int namelen;
+ if (ast_strlen_zero(item_fullname)) {
+ return 0;
+ }
/* Set key to last name or first name depending on search mode */
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))
return 0;
+ ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
+
/* Match */
item = ast_calloc(1, sizeof(*item));
if (!item)
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->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;
-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;
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;
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)) {
- 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)
@@ -504,10 +525,10 @@ static int search_directory(const char *context, struct ast_config *vmcfg, struc
res = 0;
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)) {
- 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)
@@ -521,6 +542,35 @@ static int search_directory(const char *context, struct ast_config *vmcfg, struc
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)
{
int reordered, i;
@@ -565,18 +615,11 @@ static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, stru
int count, i;
char ext[10] = "";
- if (ast_strlen_zero(context)) {
- 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")) {
+ if (digit == '0' && !goto_exten(chan, S_OR(dialcontext, "default"), "o")) {
return 0;
}
- if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
+ if (digit == '*' && !goto_exten(chan, S_OR(dialcontext, "default"), "a")) {
return 0;
}
@@ -614,16 +657,16 @@ static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, stru
if (option_debug) {
ast_debug(2, "Listing matching entries:\n");
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)) {
/* 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 {
/* 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) {
@@ -645,7 +688,7 @@ static int directory_exec(struct ast_channel *chan, void *data)
int res = 0, digit = 3;
struct ast_config *cfg, *ucfg;
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 config_flags = { 0 };
enum { FIRST, LAST, BOTH } which = LAST;
@@ -656,11 +699,6 @@ static int directory_exec(struct ast_channel *chan, void *data)
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);
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))
return -1;
- if (ast_strlen_zero(args.dialcontext))
- args.dialcontext = args.vmcontext;
-
- cfg = realtime_directory(args.vmcontext);
- if (!cfg) {
+ if (!(cfg = realtime_directory(args.vmcontext))) {
ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
return -1;
}