[asterisk-commits] tilghman: trunk r152727 - in /trunk: CHANGES apps/app_directory.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Oct 29 21:08:03 CDT 2008


Author: tilghman
Date: Wed Oct 29 21:08:02 2008
New Revision: 152727

URL: http://svn.digium.com/view/asterisk?view=rev&rev=152727
Log:
Pay attention to the searchcontexts entry in voicemail.conf (related to AST-125)

Modified:
    trunk/CHANGES
    trunk/apps/app_directory.c

Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=152727&r1=152726&r2=152727
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Wed Oct 29 21:08:02 2008
@@ -33,6 +33,9 @@
    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
 -------------

Modified: trunk/apps/app_directory.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_directory.c?view=diff&rev=152727&r1=152726&r2=152727
==============================================================================
--- trunk/apps/app_directory.c (original)
+++ trunk/apps/app_directory.c Wed Oct 29 21:08:02 2008
@@ -46,7 +46,7 @@
 
 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 @@
 "    * - 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 @@
 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 @@
 	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)
-{
-	ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, dialcontext);
+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, 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 @@
 		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 @@
 			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 @@
 	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 @@
 			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 @@
 		}
 
 		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 @@
 	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 @@
 
 	/* 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 @@
 	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 @@
 
 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 @@
 
 		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 @@
 
 			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)
@@ -519,6 +540,35 @@
 		}
 	}
 	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)
@@ -565,18 +615,11 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 	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;
 	}




More information about the asterisk-commits mailing list