]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Pay attention to the searchcontexts entry in voicemail.conf (related to AST-125)
authorTilghman Lesher <tilghman@meg.abyt.es>
Thu, 30 Oct 2008 02:08:02 +0000 (02:08 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Thu, 30 Oct 2008 02:08:02 +0000 (02:08 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@152727 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
apps/app_directory.c

diff --git a/CHANGES b/CHANGES
index 88e59fbe4c24a1d2cd78587f8add75759444175a..56769facdcc8439e8da511694f6fac349b7a9ec2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -33,6 +33,9 @@ Applications
    using MeetMeAdmin.
  * app_authenticate now gives the ability to select a prompt other than
    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
 -------------
index 30b8f7f46639e9f65a14e24464c9bf80fca38615..b2a5741ed13e6ffbdd2b712e5b988a4c879ae3f9 100644 (file)
@@ -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;
        }