| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-01-21 07:06:25 +00:00
										 |  |  |  * Copyright (C) 1999 - 2005, Digium, Inc. | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-10-02 00:58:31 +00:00
										 |  |  |  * Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * See http://www.asterisk.org for more information about
 | 
					
						
							|  |  |  |  * the Asterisk project. Please do not directly contact | 
					
						
							|  |  |  |  * any of the maintainers of this project for assistance; | 
					
						
							|  |  |  |  * the project provides a web site, mailing lists and IRC | 
					
						
							|  |  |  |  * channels for your use. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  | /*! \file
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-24 20:12:06 +00:00
										 |  |  |  * \brief Provide a directory of extensions | 
					
						
							| 
									
										
										
										
											2005-12-30 21:18:06 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \author Mark Spencer <markster@digium.com> | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup applications | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-04-29 18:48:26 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>app_voicemail</depend> | 
					
						
							| 
									
										
										
										
											2011-07-14 20:13:06 +00:00
										 |  |  | 	<support_level>core</support_level> | 
					
						
							| 
									
										
										
										
											2008-04-29 18:48:26 +00:00
										 |  |  |  ***/ | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 22:39:32 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | #include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */
 | 
					
						
							| 
									
										
										
										
											2005-04-21 06:02:45 +00:00
										 |  |  | #include "asterisk/file.h"
 | 
					
						
							|  |  |  | #include "asterisk/pbx.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/say.h"
 | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | #include "asterisk/app.h"
 | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | /*** DOCUMENTATION
 | 
					
						
							|  |  |  | 	<application name="Directory" language="en_US"> | 
					
						
							|  |  |  | 		<synopsis> | 
					
						
							|  |  |  | 			Provide directory of voicemail extensions. | 
					
						
							|  |  |  | 		</synopsis> | 
					
						
							|  |  |  | 		<syntax> | 
					
						
							|  |  |  | 			<parameter name="vm-context"> | 
					
						
							| 
									
										
										
										
											2010-03-02 19:49:48 +00:00
										 |  |  | 				<para>This is the context within voicemail.conf to use for the Directory. If not  | 
					
						
							|  |  |  | 				specified and <literal>searchcontexts=no</literal> in  | 
					
						
							|  |  |  | 				<filename>voicemail.conf</filename>, then <literal>default</literal>  | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | 				will be assumed.</para> | 
					
						
							|  |  |  | 			</parameter> | 
					
						
							|  |  |  | 			<parameter name="dial-context" required="false"> | 
					
						
							|  |  |  | 				<para>This is the dialplan context to use when looking for an | 
					
						
							|  |  |  | 				extension that the user has selected, or when jumping to the | 
					
						
							| 
									
										
										
										
											2011-07-12 20:07:20 +00:00
										 |  |  | 				<literal>o</literal> or <literal>a</literal> extension. If not | 
					
						
							|  |  |  | 				specified, the current context will be used.</para> | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | 			</parameter> | 
					
						
							|  |  |  | 			<parameter name="options" required="false"> | 
					
						
							|  |  |  | 				<optionlist> | 
					
						
							|  |  |  | 					<option name="e"> | 
					
						
							|  |  |  | 						<para>In addition to the name, also read the extension number to the | 
					
						
							|  |  |  | 						caller before presenting dialing options.</para> | 
					
						
							|  |  |  | 					</option> | 
					
						
							|  |  |  | 					<option name="f"> | 
					
						
							|  |  |  | 						<para>Allow the caller to enter the first name of a user in the | 
					
						
							|  |  |  | 						directory instead of using the last name.  If specified, the | 
					
						
							|  |  |  | 						optional number argument will be used for the number of | 
					
						
							|  |  |  | 						characters the user should enter.</para> | 
					
						
							|  |  |  | 						<argument name="n" required="true" /> | 
					
						
							|  |  |  | 					</option> | 
					
						
							|  |  |  | 					<option name="l"> | 
					
						
							|  |  |  | 						<para>Allow the caller to enter the last name of a user in the | 
					
						
							|  |  |  | 						directory.  This is the default.  If specified, the | 
					
						
							|  |  |  | 						optional number argument will be used for the number of | 
					
						
							|  |  |  | 						characters the user should enter.</para> | 
					
						
							|  |  |  | 						<argument name="n" required="true" /> | 
					
						
							|  |  |  | 					</option> | 
					
						
							|  |  |  | 					<option name="b"> | 
					
						
							|  |  |  | 						<para> Allow the caller to enter either the first or the last name | 
					
						
							|  |  |  | 						of a user in the directory.  If specified, the optional number | 
					
						
							|  |  |  | 						argument will be used for the number of characters the user should enter.</para> | 
					
						
							|  |  |  | 						<argument name="n" required="true" /> | 
					
						
							|  |  |  | 					</option> | 
					
						
							|  |  |  | 					<option name="m"> | 
					
						
							|  |  |  | 						<para>Instead of reading each name sequentially and asking for | 
					
						
							|  |  |  | 						confirmation, create a menu of up to 8 names.</para> | 
					
						
							|  |  |  | 					</option> | 
					
						
							| 
									
										
										
										
											2009-12-15 07:18:31 +00:00
										 |  |  | 					<option name="n"> | 
					
						
							|  |  |  | 						<para>Read digits even if the channel is not answered.</para> | 
					
						
							|  |  |  | 					</option> | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | 					<option name="p"> | 
					
						
							|  |  |  | 						<para>Pause for n milliseconds after the digits are typed.  This is | 
					
						
							|  |  |  | 						helpful for people with cellphones, who are not holding the | 
					
						
							|  |  |  | 						receiver to their ear while entering DTMF.</para> | 
					
						
							|  |  |  | 						<argument name="n" required="true" /> | 
					
						
							|  |  |  | 					</option> | 
					
						
							|  |  |  | 				</optionlist> | 
					
						
							|  |  |  | 				<note><para>Only one of the <replaceable>f</replaceable>, <replaceable>l</replaceable>, or <replaceable>b</replaceable> | 
					
						
							|  |  |  | 				options may be specified. <emphasis>If more than one is specified</emphasis>, then Directory will act as  | 
					
						
							|  |  |  | 				if <replaceable>b</replaceable> was specified.  The number | 
					
						
							|  |  |  | 				of characters for the user to type defaults to <literal>3</literal>.</para></note> | 
					
						
							|  |  |  | 			</parameter> | 
					
						
							|  |  |  | 		</syntax> | 
					
						
							|  |  |  | 		<description> | 
					
						
							|  |  |  | 			<para>This application will present the calling channel with a directory of extensions from which they can search | 
					
						
							|  |  |  | 			by name. The list of names and corresponding extensions is retrieved from the | 
					
						
							|  |  |  | 			voicemail configuration file, <filename>voicemail.conf</filename>.</para> | 
					
						
							|  |  |  | 			<para>This application will immediately exit if one of the following DTMF digits are | 
					
						
							|  |  |  | 			received and the extension to jump to exists:</para> | 
					
						
							|  |  |  | 			<para><literal>0</literal> - Jump to the 'o' extension, if it exists.</para> | 
					
						
							|  |  |  | 			<para><literal>*</literal> - Jump to the 'a' extension, if it exists.</para> | 
					
						
							|  |  |  | 		</description> | 
					
						
							|  |  |  | 	</application> | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  |  ***/ | 
					
						
							| 
									
										
										
										
											2009-06-07 14:55:51 +00:00
										 |  |  | static const char app[] = "Directory"; | 
					
						
							| 
									
										
										
										
											2001-04-10 17:18:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | /* For simplicity, I'm keeping the format compatible with the voicemail config,
 | 
					
						
							|  |  |  |    but i'm open to suggestions for isolating it */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | #define VOICEMAIL_CONFIG "voicemail.conf"
 | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | enum { | 
					
						
							|  |  |  | 	OPT_LISTBYFIRSTNAME = (1 << 0), | 
					
						
							|  |  |  | 	OPT_SAYEXTENSION =    (1 << 1), | 
					
						
							|  |  |  | 	OPT_FROMVOICEMAIL =   (1 << 2), | 
					
						
							|  |  |  | 	OPT_SELECTFROMMENU =  (1 << 3), | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	OPT_LISTBYLASTNAME =  (1 << 4), | 
					
						
							|  |  |  | 	OPT_LISTBYEITHER =    OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME, | 
					
						
							|  |  |  | 	OPT_PAUSE =           (1 << 5), | 
					
						
							| 
									
										
										
										
											2009-12-15 07:18:31 +00:00
										 |  |  | 	OPT_NOANSWER =        (1 << 6), | 
					
						
							| 
									
										
										
										
											2009-06-07 14:55:51 +00:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | enum { | 
					
						
							|  |  |  | 	OPT_ARG_FIRSTNAME =   0, | 
					
						
							|  |  |  | 	OPT_ARG_LASTNAME =    1, | 
					
						
							|  |  |  | 	OPT_ARG_EITHER =      2, | 
					
						
							|  |  |  | 	OPT_ARG_PAUSE =       3, | 
					
						
							|  |  |  | 	/* This *must* be the last value in this enum! */ | 
					
						
							|  |  |  | 	OPT_ARG_ARRAY_SIZE =  4, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | struct directory_item { | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	char exten[AST_MAX_EXTENSION + 1]; | 
					
						
							|  |  |  | 	char name[AST_MAX_EXTENSION + 1]; | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	char context[AST_MAX_CONTEXT + 1]; | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 	char key[50]; /* Text to order items. Either lastname+firstname or firstname+lastname */ | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	AST_LIST_ENTRY(directory_item) entry; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AST_APP_OPTIONS(directory_app_options, { | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	AST_APP_OPTION_ARG('f', OPT_LISTBYFIRSTNAME, OPT_ARG_FIRSTNAME), | 
					
						
							|  |  |  | 	AST_APP_OPTION_ARG('l', OPT_LISTBYLASTNAME, OPT_ARG_LASTNAME), | 
					
						
							|  |  |  | 	AST_APP_OPTION_ARG('b', OPT_LISTBYEITHER, OPT_ARG_EITHER), | 
					
						
							|  |  |  | 	AST_APP_OPTION_ARG('p', OPT_PAUSE, OPT_ARG_PAUSE), | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	AST_APP_OPTION('e', OPT_SAYEXTENSION), | 
					
						
							|  |  |  | 	AST_APP_OPTION('v', OPT_FROMVOICEMAIL), | 
					
						
							|  |  |  | 	AST_APP_OPTION('m', OPT_SELECTFROMMENU), | 
					
						
							| 
									
										
										
										
											2009-12-15 07:18:31 +00:00
										 |  |  | 	AST_APP_OPTION('n', OPT_NOANSWER), | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | static int compare(const char *text, const char *template) | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	char digit; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-29 20:53:53 +00:00
										 |  |  | 	if (ast_strlen_zero(text)) { | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	while (*template) { | 
					
						
							|  |  |  | 		digit = toupper(*text++); | 
					
						
							|  |  |  | 		switch (digit) { | 
					
						
							|  |  |  | 		case 0: | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		case '1': | 
					
						
							|  |  |  | 			digit = '1'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '2': | 
					
						
							|  |  |  | 		case 'A': | 
					
						
							|  |  |  | 		case 'B': | 
					
						
							|  |  |  | 		case 'C': | 
					
						
							|  |  |  | 			digit = '2'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '3': | 
					
						
							|  |  |  | 		case 'D': | 
					
						
							|  |  |  | 		case 'E': | 
					
						
							|  |  |  | 		case 'F': | 
					
						
							|  |  |  | 			digit = '3'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '4': | 
					
						
							|  |  |  | 		case 'G': | 
					
						
							|  |  |  | 		case 'H': | 
					
						
							|  |  |  | 		case 'I': | 
					
						
							|  |  |  | 			digit = '4'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '5': | 
					
						
							|  |  |  | 		case 'J': | 
					
						
							|  |  |  | 		case 'K': | 
					
						
							|  |  |  | 		case 'L': | 
					
						
							|  |  |  | 			digit = '5'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '6': | 
					
						
							|  |  |  | 		case 'M': | 
					
						
							|  |  |  | 		case 'N': | 
					
						
							|  |  |  | 		case 'O': | 
					
						
							|  |  |  | 			digit = '6'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '7': | 
					
						
							|  |  |  | 		case 'P': | 
					
						
							|  |  |  | 		case 'Q': | 
					
						
							|  |  |  | 		case 'R': | 
					
						
							|  |  |  | 		case 'S': | 
					
						
							|  |  |  | 			digit = '7'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '8': | 
					
						
							|  |  |  | 		case 'T': | 
					
						
							|  |  |  | 		case 'U': | 
					
						
							|  |  |  | 		case 'V': | 
					
						
							|  |  |  | 			digit = '8'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case '9': | 
					
						
							|  |  |  | 		case 'W': | 
					
						
							|  |  |  | 		case 'X': | 
					
						
							|  |  |  | 		case 'Y': | 
					
						
							|  |  |  | 		case 'Z': | 
					
						
							|  |  |  | 			digit = '9'; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			if (digit > ' ') | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (*template++ != digit) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-18 19:27:34 +00:00
										 |  |  | static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-07-12 20:07:20 +00:00
										 |  |  | 	if (!ast_goto_if_exists(chan, S_OR(dialcontext, chan->context), ext, 1) || | 
					
						
							| 
									
										
										
										
											2010-05-18 19:27:34 +00:00
										 |  |  | 		(!ast_strlen_zero(chan->macrocontext) && | 
					
						
							|  |  |  | 		!ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Can't find extension '%s' in current context.  " | 
					
						
							|  |  |  | 			"Not Exiting the Directory!\n", ext); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | /* play name of mailbox owner.
 | 
					
						
							|  |  |  |  * returns:  -1 for bad or missing extension | 
					
						
							|  |  |  |  *           '1' for selected entry from directory | 
					
						
							|  |  |  |  *           '*' for skipped entry from directory | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-11-14 13:18:40 +00:00
										 |  |  | static int play_mailbox_owner(struct ast_channel *chan, const char *context, | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 	const char *ext, const char *name, struct ast_flags *flags) | 
					
						
							| 
									
										
										
										
											2006-04-28 06:40:40 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 	int res = 0; | 
					
						
							| 
									
										
										
										
											2008-04-29 17:56:13 +00:00
										 |  |  | 	if ((res = ast_app_sayname(chan, ext, context)) >= 0) { | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 		ast_stopstream(chan); | 
					
						
							| 
									
										
										
										
											2006-04-11 15:38:17 +00:00
										 |  |  | 		/* If Option 'e' was specified, also read the extension number with the name */ | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 		if (ast_test_flag(flags, OPT_SAYEXTENSION)) { | 
					
						
							| 
									
										
										
										
											2006-11-17 23:18:51 +00:00
										 |  |  | 			ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); | 
					
						
							| 
									
										
										
										
											2006-04-11 15:38:17 +00:00
										 |  |  | 			res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2006-04-21 20:57:29 +00:00
										 |  |  | 		res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language); | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 		if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) { | 
					
						
							| 
									
										
										
										
											2006-11-17 23:18:51 +00:00
										 |  |  | 			ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); | 
					
						
							| 
									
										
										
										
											2006-04-11 15:38:17 +00:00
										 |  |  | 			res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags) | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context)); | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	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)); | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	} else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) { | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		ast_log(LOG_WARNING, | 
					
						
							|  |  |  | 			"Can't find extension '%s' in context '%s'.  " | 
					
						
							|  |  |  | 			"Did you pass the wrong context to Directory?\n", | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 			item->exten, S_OR(dialcontext, item->context)); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | static int select_item_pause(struct ast_channel *chan, struct ast_flags *flags, char *opts[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0, opt_pause = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_test_flag(flags, OPT_PAUSE) && !ast_strlen_zero(opts[OPT_ARG_PAUSE])) { | 
					
						
							|  |  |  | 		opt_pause = atoi(opts[OPT_ARG_PAUSE]); | 
					
						
							|  |  |  | 		if (opt_pause > 3000) { | 
					
						
							|  |  |  | 			opt_pause = 3000; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		res = ast_waitfordigit(chan, opt_pause); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[]) | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct directory_item *item, **ptr; | 
					
						
							|  |  |  | 	int i, res, loop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 	/* option p(n): cellphone pause option */ | 
					
						
							|  |  |  | 	/* allow early press of selection key */ | 
					
						
							|  |  |  | 	res = select_item_pause(chan, flags, opts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	for (ptr = items, i = 0; i < count; i++, ptr++) { | 
					
						
							|  |  |  | 		item = *ptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (loop = 3 ; loop > 0; loop--) { | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitfordigit(chan, 3000); | 
					
						
							|  |  |  | 			ast_stopstream(chan); | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-05-18 19:27:34 +00:00
										 |  |  | 			if (res == '0') { /* operator selected */ | 
					
						
							|  |  |  | 				goto_exten(chan, dialcontext, "o"); | 
					
						
							|  |  |  | 				return '0'; | 
					
						
							|  |  |  | 			} else if (res == '1') { /* Name selected */ | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 				return select_entry(chan, dialcontext, item, flags) ? -1 : 1; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			} else if (res == '*') { | 
					
						
							|  |  |  | 				/* Skip to next match in list */ | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2010-05-18 19:27:34 +00:00
										 |  |  | 			} else if (res == '#') { | 
					
						
							|  |  |  | 				/* Exit reading, continue in dialplan */ | 
					
						
							|  |  |  | 				return res; | 
					
						
							| 
									
										
										
										
											2006-04-28 06:40:40 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			if (res < 0) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			res = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 		res = 0; | 
					
						
							| 
									
										
										
										
											2006-04-28 06:40:40 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	/* Nothing was selected */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | static int select_item_menu(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[]) | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	struct directory_item **block, *item; | 
					
						
							|  |  |  | 	int i, limit, res = 0; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	char buf[9]; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 	/* option p(n): cellphone pause option */ | 
					
						
							|  |  |  | 	select_item_pause(chan, flags, opts); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	for (block = items; count; block += limit, count -= limit) { | 
					
						
							|  |  |  | 		limit = count; | 
					
						
							|  |  |  | 		if (limit > 8) | 
					
						
							|  |  |  | 			limit = 8; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (i = 0; i < limit && !res; i++) { | 
					
						
							|  |  |  | 			item = block[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			snprintf(buf, sizeof(buf), "digits/%d", i + 1); | 
					
						
							|  |  |  | 			/* Press <num> for <name>, [ extension <ext> ] */ | 
					
						
							|  |  |  | 			res = ast_streamfile(chan, "dir-multi1", chan->language); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_streamfile(chan, buf, chan->language); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_streamfile(chan, "dir-multi2", chan->language); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 				res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitfordigit(chan, 800); | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Press "9" for more names. */ | 
					
						
							|  |  |  | 		if (!res && count > limit) { | 
					
						
							|  |  |  | 			res = ast_streamfile(chan, "dir-multi9", chan->language); | 
					
						
							|  |  |  | 			if (!res) | 
					
						
							|  |  |  | 				res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!res) { | 
					
						
							|  |  |  | 			res = ast_waitfordigit(chan, 3000); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (res && res > '0' && res < '1' + limit) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 			return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (res < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		res = 0; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Nothing was selected */ | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | static struct ast_config *realtime_directory(char *context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 	struct ast_config *cfg; | 
					
						
							|  |  |  | 	struct ast_config *rtdata; | 
					
						
							|  |  |  | 	struct ast_category *cat; | 
					
						
							|  |  |  | 	struct ast_variable *var; | 
					
						
							|  |  |  | 	char *mailbox; | 
					
						
							| 
									
										
										
										
											2006-09-20 20:40:39 +00:00
										 |  |  | 	const char *fullname; | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	const char *hidefromdir, *searchcontexts = NULL; | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 	char tmp[100]; | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	struct ast_flags config_flags = { 0 }; | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Load flat file config. */ | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (!cfg) { | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 		/* Loading config failed. */ | 
					
						
							|  |  |  | 		ast_log(LOG_WARNING, "Loading config failed.\n"); | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2008-09-12 23:30:03 +00:00
										 |  |  | 	} else if (cfg == CONFIG_STATUS_FILEINVALID) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", VOICEMAIL_CONFIG); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 	/* Get realtime entries, categorized by their mailbox number
 | 
					
						
							|  |  |  | 	   and present in the requested context */ | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 	/* if there are no results, just return the entries from the config file */ | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	if (!rtdata) { | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 		return cfg; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-14 22:32:13 +00:00
										 |  |  | 	mailbox = NULL; | 
					
						
							|  |  |  | 	while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 		const char *context = ast_variable_retrieve(rtdata, mailbox, "context"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 		fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) { | 
					
						
							|  |  |  | 			/* Skip hidden */ | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, "")); | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* 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); | 
					
						
							| 
									
										
										
										
											2008-12-17 21:17:20 +00:00
										 |  |  | 				if (rtdata) { | 
					
						
							|  |  |  | 					ast_config_destroy(rtdata); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 				return NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ast_category_append(cfg, cat); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if ((var = ast_variable_new(mailbox, tmp, ""))) { | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 			ast_variable_append(cat, var); | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 			ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-04-06 18:55:33 +00:00
										 |  |  | 	ast_config_destroy(rtdata); | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return cfg; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct directory_item *item; | 
					
						
							|  |  |  | 	const char *key = NULL; | 
					
						
							|  |  |  | 	int namelen; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	if (ast_strlen_zero(item_fullname)) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Set key to last name or first name depending on search mode */ | 
					
						
							|  |  |  | 	if (!use_first_name) | 
					
						
							|  |  |  | 		key = strchr(item_fullname, ' '); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (key) | 
					
						
							|  |  |  | 		key++; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		key = item_fullname; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (compare(key, pattern_ext)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	ast_debug(1, "Found match %s@%s\n", item_ext, item_context); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	/* Match */ | 
					
						
							|  |  |  | 	item = ast_calloc(1, sizeof(*item)); | 
					
						
							|  |  |  | 	if (!item) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	ast_copy_string(item->context, item_context, sizeof(item->context)); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	ast_copy_string(item->name, item_fullname, sizeof(item->name)); | 
					
						
							|  |  |  | 	ast_copy_string(item->exten, item_ext, sizeof(item->exten)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_copy_string(item->key, key, sizeof(item->key)); | 
					
						
							|  |  |  | 	if (key != item_fullname) { | 
					
						
							|  |  |  | 		/* Key is the last name. Append first name to key in order to sort Last,First */ | 
					
						
							|  |  |  | 		namelen = key - item_fullname - 1; | 
					
						
							|  |  |  | 		if (namelen > sizeof(item->key) - strlen(item->key) - 1) | 
					
						
							|  |  |  | 			namelen = sizeof(item->key) - strlen(item->key) - 1; | 
					
						
							|  |  |  | 		strncat(item->key, item_fullname, namelen); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*result = item; | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef AST_LIST_HEAD_NOLOCK(, directory_item) itemlist; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 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) | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	struct ast_variable *v; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat; | 
					
						
							|  |  |  | 	struct directory_item *item; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	int res; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_debug(2, "Pattern: %s\n", ext); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (v = ast_variable_browse(vmcfg, context); v; v = v->next) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* Ignore hidden */ | 
					
						
							|  |  |  | 		if (strcasestr(v->value, "hidefromdir=yes")) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ast_copy_string(buf, v->value, sizeof(buf)); | 
					
						
							|  |  |  | 		bufptr = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* password,Full Name,email,pager,options */ | 
					
						
							|  |  |  | 		strsep(&bufptr, ","); | 
					
						
							|  |  |  | 		pos = strsep(&bufptr, ","); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 07:39:44 +00:00
										 |  |  | 		/* No name to compare against */ | 
					
						
							|  |  |  | 		if (ast_strlen_zero(pos)) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		res = 0; | 
					
						
							|  |  |  | 		if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 			res = check_match(&item, context, pos, v->name, ext, 0 /* use_first_name */); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 			res = check_match(&item, context, pos, v->name, ext, 1 /* use_first_name */); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		if (!res) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		else if (res < 0) | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		AST_LIST_INSERT_TAIL(alist, item, entry); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ucfg) { | 
					
						
							|  |  |  | 		for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { | 
					
						
							| 
									
										
										
										
											2008-08-10 14:45:25 +00:00
										 |  |  | 			const char *position; | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			if (!strcasecmp(cat, "general")) | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			/* Find all candidate extensions */ | 
					
						
							| 
									
										
										
										
											2008-08-10 14:45:25 +00:00
										 |  |  | 			position = ast_variable_retrieve(ucfg, cat, "fullname"); | 
					
						
							|  |  |  | 			if (!position) | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 				continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 			res = 0; | 
					
						
							|  |  |  | 			if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 				res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 				res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 			if (!res) | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			else if (res < 0) | 
					
						
							|  |  |  | 				return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			AST_LIST_INSERT_TAIL(alist, item, entry); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 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); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | static void sort_items(struct directory_item **sorted, int count) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int reordered, i; | 
					
						
							|  |  |  | 	struct directory_item **ptr, *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (count < 2) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Bubble-sort items by the key */ | 
					
						
							|  |  |  | 	do { | 
					
						
							|  |  |  | 		reordered = 0; | 
					
						
							|  |  |  | 		for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) { | 
					
						
							|  |  |  | 			if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) { | 
					
						
							|  |  |  | 				tmp = ptr[0]; | 
					
						
							|  |  |  | 				ptr[0] = ptr[1]; | 
					
						
							|  |  |  | 				ptr[1] = tmp; | 
					
						
							|  |  |  | 				reordered++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} while (reordered); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 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[]) | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* Read in the first three digits..  "digit" is the first digit, already read */ | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE; | 
					
						
							|  |  |  | 	struct directory_item *item, **ptr, **sorted = NULL; | 
					
						
							|  |  |  | 	int count, i; | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	char ext[10] = ""; | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-12 20:07:20 +00:00
										 |  |  | 	if (digit == '0' && !goto_exten(chan, dialcontext, "o")) { | 
					
						
							| 
									
										
										
										
											2009-12-15 02:29:50 +00:00
										 |  |  | 		return digit; | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-07-12 20:07:20 +00:00
										 |  |  | 	if (digit == '*' && !goto_exten(chan, dialcontext, "a")) { | 
					
						
							| 
									
										
										
										
											2009-12-15 02:29:50 +00:00
										 |  |  | 		return digit; | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	ext[0] = digit; | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0) | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	if (res) | 
					
						
							|  |  |  | 		goto exit; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	/* Count items in the list */ | 
					
						
							|  |  |  | 	count = 0; | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE(&alist, item, entry) { | 
					
						
							|  |  |  | 		count++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	if (count < 1) { | 
					
						
							|  |  |  | 		res = ast_streamfile(chan, "dir-nomatch", chan->language); | 
					
						
							|  |  |  | 		goto exit; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	/* Create plain array of pointers to items (for sorting) */ | 
					
						
							|  |  |  | 	sorted = ast_calloc(count, sizeof(*sorted)); | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	ptr = sorted; | 
					
						
							|  |  |  | 	AST_LIST_TRAVERSE(&alist, item, entry) { | 
					
						
							|  |  |  | 		*ptr++ = item; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Sort items */ | 
					
						
							|  |  |  | 	sort_items(sorted, count); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (option_debug) { | 
					
						
							|  |  |  | 		ast_debug(2, "Listing matching entries:\n"); | 
					
						
							|  |  |  | 		for (ptr = sorted, i = 0; i < count; i++, ptr++) { | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 			ast_debug(2, "%s: %s\n", ptr[0]->exten, ptr[0]->name); | 
					
						
							| 
									
										
										
										
											2004-06-22 03:43:41 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_test_flag(flags, OPT_SELECTFROMMENU)) { | 
					
						
							|  |  |  | 		/* Offer multiple entries at the same time */ | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 		res = select_item_menu(chan, sorted, count, dialcontext, flags, opts); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		/* Offer entries one by one */ | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 		res = select_item_seq(chan, sorted, count, dialcontext, flags, opts); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!res) { | 
					
						
							|  |  |  | 		res = ast_streamfile(chan, "dir-nomore", chan->language); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exit: | 
					
						
							|  |  |  | 	if (sorted) | 
					
						
							|  |  |  | 		ast_free(sorted); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((item = AST_LIST_REMOVE_HEAD(&alist, entry))) | 
					
						
							|  |  |  | 		ast_free(item); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | static int directory_exec(struct ast_channel *chan, const char *data) | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	int res = 0, digit = 3; | 
					
						
							| 
									
										
										
										
											2006-09-16 23:53:58 +00:00
										 |  |  | 	struct ast_config *cfg, *ucfg; | 
					
						
							| 
									
										
										
										
											2006-09-20 20:40:39 +00:00
										 |  |  | 	const char *dirintro; | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, }; | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 	struct ast_flags flags = { 0 }; | 
					
						
							| 
									
										
										
										
											2007-08-16 21:09:46 +00:00
										 |  |  | 	struct ast_flags config_flags = { 0 }; | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 	enum { FIRST, LAST, BOTH } which = LAST; | 
					
						
							|  |  |  | 	char digits[9] = "digits/3"; | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | 	AST_DECLARE_APP_ARGS(args, | 
					
						
							|  |  |  | 		AST_APP_ARG(vmcontext); | 
					
						
							|  |  |  | 		AST_APP_ARG(dialcontext); | 
					
						
							|  |  |  | 		AST_APP_ARG(options); | 
					
						
							|  |  |  | 	); | 
					
						
							| 
									
										
										
										
											2004-08-05 22:02:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-05-10 13:22:15 +00:00
										 |  |  | 	parse = ast_strdupa(data); | 
					
						
							| 
									
										
										
										
											2006-01-21 17:50:04 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | 	AST_STANDARD_APP_ARGS(args, parse); | 
					
						
							| 
									
										
										
										
											2007-12-05 16:25:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options)) | 
					
						
							|  |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-30 02:08:02 +00:00
										 |  |  | 	if (!(cfg = realtime_directory(args.vmcontext))) { | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | 		ast_log(LOG_ERROR, "Unable to read the configuration data!\n"); | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 		return -1; | 
					
						
							| 
									
										
										
										
											2005-10-19 18:19:02 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-02-09 11:27:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-12 23:30:03 +00:00
										 |  |  | 	if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Config file users.conf is in an invalid format.  Aborting.\n"); | 
					
						
							|  |  |  | 		ucfg = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-03-03 05:31:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-11-30 20:09:58 +00:00
										 |  |  | 	dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro"); | 
					
						
							| 
									
										
										
										
											2005-10-26 19:48:14 +00:00
										 |  |  | 	if (ast_strlen_zero(dirintro)) | 
					
						
							| 
									
										
										
										
											2004-04-29 13:53:38 +00:00
										 |  |  | 		dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); | 
					
						
							| 
									
										
										
										
											2010-05-18 19:27:34 +00:00
										 |  |  | 	/* the above prompts probably should be modified to include 0 for dialing operator
 | 
					
						
							|  |  |  | 	   and # for exiting (continues in dialplan) */ | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { | 
					
						
							|  |  |  | 		if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) { | 
					
						
							|  |  |  | 			digit = atoi(opts[OPT_ARG_EITHER]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		which = BOTH; | 
					
						
							|  |  |  | 	} else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { | 
					
						
							|  |  |  | 		if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) { | 
					
						
							|  |  |  | 			digit = atoi(opts[OPT_ARG_FIRSTNAME]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		which = FIRST; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) { | 
					
						
							|  |  |  | 			digit = atoi(opts[OPT_ARG_LASTNAME]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		which = LAST; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If no options specified, search by last name */ | 
					
						
							|  |  |  | 	if (!ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && !ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { | 
					
						
							|  |  |  | 		ast_set_flag(&flags, OPT_LISTBYLASTNAME); | 
					
						
							|  |  |  | 		which = LAST; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (digit > 9) { | 
					
						
							|  |  |  | 		digit = 9; | 
					
						
							|  |  |  | 	} else if (digit < 1) { | 
					
						
							|  |  |  | 		digit = 3; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	digits[7] = digit + '0'; | 
					
						
							| 
									
										
										
										
											2005-10-04 22:44:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 07:18:31 +00:00
										 |  |  | 	if (chan->_state != AST_STATE_UP) { | 
					
						
							|  |  |  | 		if (!ast_test_flag(&flags, OPT_NOANSWER)) { | 
					
						
							|  |  |  | 			/* Otherwise answer unless we're supposed to read while on-hook */ | 
					
						
							|  |  |  | 			res = ast_answer(chan); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2005-10-04 22:44:15 +00:00
										 |  |  | 	for (;;) { | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		if (!ast_strlen_zero(dirintro) && !res) { | 
					
						
							| 
									
										
										
										
											2006-11-17 23:18:51 +00:00
										 |  |  | 			res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY); | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		} else if (!res) { | 
					
						
							| 
									
										
										
										
											2008-04-15 20:27:04 +00:00
										 |  |  | 			/* Stop playing sounds as soon as we have a digit. */ | 
					
						
							|  |  |  | 			res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			if (!res) { | 
					
						
							|  |  |  | 				res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!res) { | 
					
						
							|  |  |  | 				res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!res) { | 
					
						
							|  |  |  | 				res = ast_stream_and_wait(chan,  | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 					which == FIRST ? "dir-first" : | 
					
						
							|  |  |  | 					which == LAST ? "dir-last" : | 
					
						
							| 
									
										
										
										
											2008-04-15 20:27:04 +00:00
										 |  |  | 					"dir-firstlast", AST_DIGIT_ANY); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!res) { | 
					
						
							| 
									
										
										
										
											2009-12-15 00:54:44 +00:00
										 |  |  | 				res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY); | 
					
						
							| 
									
										
										
										
											2008-04-15 20:27:04 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2008-03-20 05:06:12 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2005-10-04 22:44:15 +00:00
										 |  |  | 		ast_stopstream(chan); | 
					
						
							|  |  |  | 		if (!res) | 
					
						
							|  |  |  | 			res = ast_waitfordigit(chan, 5000); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (res <= 0) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-11 07:03:51 +00:00
										 |  |  | 		res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 		if (res) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		res = ast_waitstream(chan, AST_DIGIT_ANY); | 
					
						
							|  |  |  | 		ast_stopstream(chan); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (res) | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-16 23:53:58 +00:00
										 |  |  | 	if (ucfg) | 
					
						
							|  |  |  | 		ast_config_destroy(ucfg); | 
					
						
							| 
									
										
										
										
											2005-01-25 06:10:20 +00:00
										 |  |  | 	ast_config_destroy(cfg); | 
					
						
							| 
									
										
										
										
											2008-01-14 22:11:50 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return res < 0 ? -1 : 0; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2005-10-18 22:52:21 +00:00
										 |  |  | 	int res; | 
					
						
							|  |  |  | 	res = ast_unregister_application(app); | 
					
						
							|  |  |  | 	return res; | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-11-01 21:10:07 +00:00
										 |  |  | 	return ast_register_application_xml(app, directory_exec); | 
					
						
							| 
									
										
										
										
											1999-10-30 01:01:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Directory"); |