[asterisk-commits] russell: branch group/sip_session_timers r98976 - in /team/group/sip_session_...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 16 15:25:23 CST 2008


Author: russell
Date: Wed Jan 16 15:25:22 2008
New Revision: 98976

URL: http://svn.digium.com/view/asterisk?view=rev&rev=98976
Log:
resolve, reset

Added:
    team/group/sip_session_timers/apps/app_jack.c
      - copied unchanged from r98975, trunk/apps/app_jack.c
    team/group/sip_session_timers/channels/console_board.c
      - copied unchanged from r98975, trunk/channels/console_board.c
    team/group/sip_session_timers/configs/phoneprov.conf.sample
      - copied unchanged from r98975, trunk/configs/phoneprov.conf.sample
    team/group/sip_session_timers/doc/tex/phoneprov.tex
      - copied unchanged from r98975, trunk/doc/tex/phoneprov.tex
    team/group/sip_session_timers/images/font.png
      - copied unchanged from r98975, trunk/images/font.png
    team/group/sip_session_timers/phoneprov/
      - copied from r98975, trunk/phoneprov/
    team/group/sip_session_timers/phoneprov/000000000000-directory.xml
      - copied unchanged from r98975, trunk/phoneprov/000000000000-directory.xml
    team/group/sip_session_timers/phoneprov/000000000000-phone.cfg
      - copied unchanged from r98975, trunk/phoneprov/000000000000-phone.cfg
    team/group/sip_session_timers/phoneprov/000000000000.cfg
      - copied unchanged from r98975, trunk/phoneprov/000000000000.cfg
    team/group/sip_session_timers/phoneprov/polycom.xml
      - copied unchanged from r98975, trunk/phoneprov/polycom.xml
    team/group/sip_session_timers/res/res_phoneprov.c
      - copied unchanged from r98975, trunk/res/res_phoneprov.c
Removed:
    team/group/sip_session_timers/pbx/kdeconsole_main.cc
    team/group/sip_session_timers/pbx/pbx_kdeconsole.cc
    team/group/sip_session_timers/pbx/pbx_kdeconsole.h
Modified:
    team/group/sip_session_timers/   (props changed)
    team/group/sip_session_timers/CHANGES
    team/group/sip_session_timers/Makefile
    team/group/sip_session_timers/apps/app_directory.c
    team/group/sip_session_timers/apps/app_followme.c
    team/group/sip_session_timers/apps/app_meetme.c
    team/group/sip_session_timers/apps/app_queue.c
    team/group/sip_session_timers/apps/app_stack.c
    team/group/sip_session_timers/apps/app_voicemail.c
    team/group/sip_session_timers/build_tools/menuselect-deps.in
    team/group/sip_session_timers/cdr/cdr_adaptive_odbc.c
    team/group/sip_session_timers/cdr/cdr_odbc.c
    team/group/sip_session_timers/channels/Makefile
    team/group/sip_session_timers/channels/chan_console.c
    team/group/sip_session_timers/channels/chan_gtalk.c
    team/group/sip_session_timers/channels/chan_iax2.c
    team/group/sip_session_timers/channels/chan_local.c
    team/group/sip_session_timers/channels/chan_mgcp.c
    team/group/sip_session_timers/channels/chan_oss.c
    team/group/sip_session_timers/channels/chan_sip.c
    team/group/sip_session_timers/channels/chan_skinny.c
    team/group/sip_session_timers/channels/chan_zap.c
    team/group/sip_session_timers/channels/console_gui.c
    team/group/sip_session_timers/channels/console_video.c
    team/group/sip_session_timers/channels/console_video.h
    team/group/sip_session_timers/channels/vgrabbers.c
    team/group/sip_session_timers/codecs/Makefile
    team/group/sip_session_timers/codecs/codec_g722.c
    team/group/sip_session_timers/codecs/codec_resample.c
    team/group/sip_session_timers/codecs/codec_speex.c
    team/group/sip_session_timers/codecs/codec_zap.c
    team/group/sip_session_timers/configs/cdr_adaptive_odbc.conf.sample
    team/group/sip_session_timers/configs/manager.conf.sample
    team/group/sip_session_timers/configs/modules.conf.sample
    team/group/sip_session_timers/configs/queues.conf.sample
    team/group/sip_session_timers/configs/sip.conf.sample
    team/group/sip_session_timers/configs/voicemail.conf.sample
    team/group/sip_session_timers/configs/zapata.conf.sample
    team/group/sip_session_timers/configure
    team/group/sip_session_timers/configure.ac
    team/group/sip_session_timers/doc/manager_1_1.txt
    team/group/sip_session_timers/doc/tex/Makefile
    team/group/sip_session_timers/doc/tex/asterisk.tex
    team/group/sip_session_timers/doc/tex/qos.tex
    team/group/sip_session_timers/doc/tex/realtime.tex
    team/group/sip_session_timers/formats/format_sln16.c
    team/group/sip_session_timers/funcs/func_groupcount.c
    team/group/sip_session_timers/funcs/func_strings.c
    team/group/sip_session_timers/images/kpad2.jpg
    team/group/sip_session_timers/include/asterisk/autoconfig.h.in
    team/group/sip_session_timers/include/asterisk/frame.h
    team/group/sip_session_timers/include/asterisk/localtime.h
    team/group/sip_session_timers/include/asterisk/manager.h
    team/group/sip_session_timers/include/asterisk/translate.h
    team/group/sip_session_timers/main/Makefile
    team/group/sip_session_timers/main/abstract_jb.c
    team/group/sip_session_timers/main/acl.c
    team/group/sip_session_timers/main/ast_expr2.c
    team/group/sip_session_timers/main/ast_expr2.fl
    team/group/sip_session_timers/main/ast_expr2.h
    team/group/sip_session_timers/main/ast_expr2.y
    team/group/sip_session_timers/main/ast_expr2f.c
    team/group/sip_session_timers/main/asterisk.c
    team/group/sip_session_timers/main/audiohook.c
    team/group/sip_session_timers/main/autoservice.c
    team/group/sip_session_timers/main/channel.c
    team/group/sip_session_timers/main/cli.c
    team/group/sip_session_timers/main/db.c
    team/group/sip_session_timers/main/dial.c
    team/group/sip_session_timers/main/editline/readline.c
    team/group/sip_session_timers/main/frame.c
    team/group/sip_session_timers/main/http.c
    team/group/sip_session_timers/main/manager.c
    team/group/sip_session_timers/main/pbx.c
    team/group/sip_session_timers/main/rtp.c
    team/group/sip_session_timers/main/stdtime/localtime.c
    team/group/sip_session_timers/main/translate.c
    team/group/sip_session_timers/main/utils.c
    team/group/sip_session_timers/makeopts.in
    team/group/sip_session_timers/pbx/pbx_dundi.c
    team/group/sip_session_timers/pbx/pbx_gtkconsole.c
    team/group/sip_session_timers/pbx/pbx_realtime.c
    team/group/sip_session_timers/res/Makefile
    team/group/sip_session_timers/res/ael/ael.flex
    team/group/sip_session_timers/res/ael/ael_lex.c
    team/group/sip_session_timers/res/res_agi.c
    team/group/sip_session_timers/res/res_features.c
    team/group/sip_session_timers/res/res_jabber.c
    team/group/sip_session_timers/res/res_odbc.c
    team/group/sip_session_timers/utils/astman.c

Propchange: team/group/sip_session_timers/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/group/sip_session_timers/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/sip_session_timers/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Jan 16 15:25:22 2008
@@ -23,3 +23,4 @@
 autom4te.cache
 makeopts.embed_rules
 aclocal.m4
+update.log

Propchange: team/group/sip_session_timers/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed Jan 16 15:25:22 2008
@@ -1,1 +1,1 @@
-/trunk:1-97164
+/trunk:1-98975

Modified: team/group/sip_session_timers/CHANGES
URL: http://svn.digium.com/view/asterisk/team/group/sip_session_timers/CHANGES?view=diff&rev=98976&r1=98975&r2=98976
==============================================================================
--- team/group/sip_session_timers/CHANGES (original)
+++ team/group/sip_session_timers/CHANGES Wed Jan 16 15:25:22 2008
@@ -35,31 +35,37 @@
   * Added Masquerade manager event for when a masquerade happens between
      two channels.
   * Added "manager reload" command for the CLI
+  * Lots of commands that only provided information are now allowed under the
+     Reporting privilege, instead of only under Call or System.
+  * The IAX* commands now require either System or Reporting privilege, to
+     mirror the privileges of the SIP* commands.
 
 Dialplan functions
 ------------------
   * Added the DEVICE_STATE() dialplan function which allows retrieving any device
-    state in the dialplan, as well as creating custom device states that are
-    controllable from the dialplan.
+     state in the dialplan, as well as creating custom device states that are
+     controllable from the dialplan.
   * Extend CALLERID() function with "pres" and "ton" parameters to
      fetch string representation of calling number presentation indicator
      and numeric representation of type of calling number value.
   * MailboxExists converted to dialplan function
   * A new option to Dial() for telling IP phones not to count the call
-    as "missed" when dial times out and cancels.
+     as "missed" when dial times out and cancels.
   * Added LOCK(), TRYLOCK(), and UNLOCK(), which provide a single level dialplan
-    mutex.  No deadlocks are possible, as LOCK() only allows a single lock to be
-    held for any given channel.  Also, locks are automatically freed when a
-    channel is hung up.
+     mutex.  No deadlocks are possible, as LOCK() only allows a single lock to be
+     held for any given channel.  Also, locks are automatically freed when a
+     channel is hung up.
   * Added HINT() dialplan function that allows retrieving hint information.
-    Hints are mappings between extensions and devices for the sake of 
-    determining the state of an extension.  This function can retrieve the list
-    of devices or the name associated with a hint.
+     Hints are mappings between extensions and devices for the sake of 
+     determining the state of an extension.  This function can retrieve the list
+     of devices or the name associated with a hint.
   * Added EXTENSION_STATE() dialplan function which allows retrieving the state
     of any extension.
   * Added SYSINFO() dialplan function which allows retrieval of system information
   * Added a new dialplan function, DIALPLAN_EXISTS(), which allows you to check for
      the existence of a dialplan target.
+  * Added two new dialplan functions, TOUPPER and TOLOWER, which convert a string to
+     upper and lower case, respectively.
 
 CLI Changes
 -----------
@@ -72,6 +78,7 @@
   * Enhanced "agi debug" to print the channel name as a prefix to the debug
      output to make debugging on busy systems much easier.
   * New CLI commands "dialplan set extenpatternmatching true/false"
+  * New CLI command: "core set chanvar" to set a channel variable from the CLI.
 
 SIP changes
 -----------
@@ -109,13 +116,15 @@
      states it is not needed. For phones, however, that do require it the "registertrying" option
      has been added so it can be enabled. 
   * A new option called "callcounter" (global/peer/user level) enables call counters needed
-    for better status reports needed for queues and SIP subscriptions. (Call-Limit was previously
-    used to enable this functionality).
+     for better status reports needed for queues and SIP subscriptions. (Call-Limit was previously
+     used to enable this functionality).
   * New settings for timer T1 and timer B on a global level or per device. This makes it 
-    possible to force timeout faster on non-responsive SIP servers. These settings are
-    considered advanced, so don't use them unless you have a problem.
+     possible to force timeout faster on non-responsive SIP servers. These settings are
+     considered advanced, so don't use them unless you have a problem.
   * Added a dial string option to be able to set the To: header in an INVITE to any
-    SIP uri.
+     SIP uri.
+  * Added a new global and per-peer option, qualifyfreq, which allows you to configure
+     the qualify frequency.
 
 IAX2 changes
 ------------
@@ -143,11 +152,6 @@
   * Added experimental support for video send & receive to chan_oss.
     This requires SDL and ffmpeg/avcodec, plus Video4Linux or X11 to act as
     a video source.
-  * Added a new channel driver, chan_console, which uses portaudio as a cross
-     platform audio interface.  It was written as a channel driver that would
-     work with Mac CoreAudio, but portaudio supports a number of other audio
-     interfaces, as well. Note that this channel driver requires v19 or higher
-     of portaudio; older versions have a different API.
 
 Phone channel changes (chan_phone)
 ----------------------------------
@@ -174,8 +178,8 @@
 ----------------------------------------
   * SS7 support in chan_zap (via libss7 library)
   * In India, some carriers transmit CID via dtmf. Some code has been added
-    that will handle some situations. The cidstart=polarity_IN choice has been added for
-    those carriers that transmit CID via dtmf after a polarity change.
+     that will handle some situations. The cidstart=polarity_IN choice has been added for
+     those carriers that transmit CID via dtmf after a polarity change.
   * CID matching information is now shown when doing 'dialplan show'.
   * Added zap show version CLI command to chan_zap.
   * Added setvar support to zapata.conf channel entries.
@@ -184,12 +188,27 @@
      the script specified in the mwimonitornotify option is executed.  An internal
      event indicating the new state of the mailbox is also generated, so that
      the normal MWI facilities in Asterisk work as usual.
-
-A new channel driver: Unistim
------------------------------
+  * Added signalling type 'auto', which attempts to use the same signalling type
+     for a channel as configured in Zaptel. This is primarily designed for analog
+     ports, but will also work for digital ports that are configured for FXS or FXO
+     signalling types. This mode is also the default now, so if your zapata.conf
+     does not specify signalling for a channel (which is unlikely as the sample
+     configuration file has always recommended specifying it for every channel) then
+     the 'auto' mode will be used for that channel if possible.
+  * Added a 'zap set dnd' command to allow CLI control of the Do-Not-Disturb
+     state for a channel; also ensured that the DNDState Manager event is
+     emitted no matter how the DND state is set or cleared.
+
+New Channel Drivers
+-------------------
   * Added a new channel driver, chan_unistim.  See doc/unistim.txt and
      configs/unistim.conf.sample for details.  This new channel driver allows
      you to use Nortel i2002, i2004, and i2050 phones with Asterisk.
+  * Added a new channel driver, chan_console, which uses portaudio as a cross
+     platform audio interface.  It was written as a channel driver that would
+     work with Mac CoreAudio, but portaudio supports a number of other audio
+     interfaces, as well. Note that this channel driver requires v19 or higher
+     of portaudio; older versions have a different API.
  
 DUNDi changes
 -------------
@@ -237,6 +256,8 @@
      future.  The default is the old behavior, lockfile.  However, there is a
      new method, "flock", that uses a different method for situations where the
      lockfile will not work, such as on SMB/CIFS mounts.
+  * Added the ability to backup deleted messages, to ease recovery in the case
+     that a user accidentally deletes a message, and discovers that they need it.
 
 Queue changes
 -------------
@@ -265,6 +286,9 @@
   * Added new channel variable QUEUE_MIN_PENALTY
   * QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY may be adjusted in mid-call by defining
      rules in queuerules.conf. See configs/queuerules.conf.sample for details
+  * Added a new parameter for member definition, called state_interface. This may be
+    used so that a member may be called via one interface but have a different interface's
+    device state reported.
 
 MeetMe Changes
 --------------
@@ -330,8 +354,8 @@
      to this music on hold class.
   * Support for realtime music on hold has been added.
   * In conjunction with the realtime music on hold, a general section has
-    been added to musiconhold.conf, its sole variable is cachertclasses. If this
-    is set, then music on hold classes found in realtime will be cached in memory.
+     been added to musiconhold.conf, its sole variable is cachertclasses. If this
+     is set, then music on hold classes found in realtime will be cached in memory.
 
 AEL Changes
 -----------
@@ -353,11 +377,11 @@
      fashion:  Set(LOCAL(myvar)=someval);  ("local" is now
      an AEL keyword).
   * utils/conf2ael introduced. Will convert an extensions.conf
-    file into extensions.ael. Very crude and unfinished, but 
-    will be improved as time goes by. Should be useful for a
-    first pass at conversion.
+     file into extensions.ael. Very crude and unfinished, but 
+     will be improved as time goes by. Should be useful for a
+     first pass at conversion.
   * aelparse will now read extensions.conf to see if a referenced
-    macro or context is there before issueing a warning.
+     macro or context is there before issueing a warning.
 
 Call Features (res_features) Changes
 ------------------------------------
@@ -397,6 +421,34 @@
      and to ensure that the oldest log file gets deleted.
   * Added realtime support for the queue log
 
+Miscellaneous New Modules
+-------------------------
+  * Added a new CDR module, cdr_sqlite3_custom.
+  * Added a new realtime configuration module, res_config_sqlite
+  * Added a new codec translation module, codec_resample, which re-samples
+     signed linear audio between 8 kHz and 16 kHz to help support wideband
+     codecs.
+  * Added a new module, res_phoneprov, which allows auto-provisioning of phones
+     based on configuration templates that use Asterisk dialplan function and
+     variable substitution.  It should be possible to create phone profiles and
+     templates that work for the majority of phones provisioned over http. It
+     is currently only intended to provision a single user account per phone.
+     An example profile and set of templates for Polycom phones is provided.
+     NOTE: Polycom firmware is not included, but should be placed in
+     AST_DATA_DIR/phoneprov/configs to match up with the included templates.
+  * Added a new module, app_jack, which provides interfaces to JACK, the Jack
+     Audio Connection Kit (http://www.jackaudio.org/).  Two interfaces are
+     provided; there is a JACK() application, and a JACK_HOOK() function.  Both
+     interfaces create an input and output JACK port.  The application makes
+     these ports the endpoint of the call.  The audio coming from the channel
+     goes out the output port and whatever comes back in on the input port is
+     what gets sent to the channel.  The JACK_HOOK() function turns on a JACK
+     audiohook on the channel.  This lets you run the audio coming from a
+     channel through JACK, and whatever comes back in is what gets forwarded
+     on as the channel's audio.  This is very useful for building custom
+     vocoders or doing recording or analysis of the channel's audio in another
+     application.
+
 Miscellaneous 
 -------------
   * Ability to use libcap to set high ToS bits when non-root
@@ -405,10 +457,8 @@
   * Added maxfiles option to options section of asterisk.conf which allows you to specify
      what Asterisk should set as the maximum number of open files when it loads.
   * Added the jittertargetextra configuration option.
-  * Added a new CDR module, cdr_sqlite3_custom.
   * The cdr_manager module has a [mappings] feature, like cdr_custom,
     to add fields to the manager event from the CDR variables.
-  * Added a new realtime configuration module, res_config_sqlite
   * Added support for setting the CoS for VLAN traffic (802.1p).  See the sample
      configuration files for the IP channel drivers.  The new option is "cos".
      This information is also documented in doc/qos.tex, or the IP Quality of Service
@@ -420,16 +470,15 @@
   * Added support for writing and running your dialplan in lua.  See
      configs/extensions.lua.sample for examples of how to do this.
   * A new extension pattern matching algorithm, based on a trie, is introduced
-    here, that could noticeably speed up mid-sized to large dialplans.
-    It is NOT used by default, as duplicating the behaviour of the old pattern
-    matcher is still under development. A config file option, in extensions.conf,
-    in the [general] section, called "extenpatternmatchingnew", is by default
-    set to false; setting that to true will force the use of the new algorithm.
-    Also, the cli commands "dialplan set extenpatternmatchingnew true/false" can
-    be used to switch the algorithms at run time.
+     here, that could noticeably speed up mid-sized to large dialplans.
+     It is NOT used by default, as duplicating the behaviour of the old pattern
+     matcher is still under development. A config file option, in extensions.conf,
+     in the [general] section, called "extenpatternmatchingnew", is by default
+     set to false; setting that to true will force the use of the new algorithm.
+     Also, the cli commands "dialplan set extenpatternmatchingnew true/false" can
+     be used to switch the algorithms at run time.
   * A new option when starting a remote asterisk (rasterisk, asterisk -r) for
-    specifying which socket to use to connect to the running Asterisk daemon
-    (-s)
-  * Added a new codec translation module, codec_resample, which re-samples
-     signed linear audio between 8 kHz and 16 kHz to help support wideband
-     codecs.
+     specifying which socket to use to connect to the running Asterisk daemon
+     (-s)
+  * Added logging to 'make update' command.  See update.log
+

Modified: team/group/sip_session_timers/Makefile
URL: http://svn.digium.com/view/asterisk/team/group/sip_session_timers/Makefile?view=diff&rev=98976&r1=98975&r2=98976
==============================================================================
--- team/group/sip_session_timers/Makefile (original)
+++ team/group/sip_session_timers/Makefile Wed Jan 16 15:25:22 2008
@@ -450,6 +450,10 @@
 # Should static HTTP be installed during make samples or even with its own target ala
 # webvoicemail?  There are portions here that *could* be customized but might also be
 # improved a lot.  I'll put it here for now.
+	mkdir -p $(DESTDIR)$(ASTDATADIR)/phoneprov
+	for x in phoneprov/*; do \
+		$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/phoneprov ; \
+	done
 	mkdir -p $(DESTDIR)$(ASTDATADIR)/static-http
 	for x in static-http/*; do \
 		$(INSTALL) -m 644 $$x $(DESTDIR)$(ASTDATADIR)/static-http ; \
@@ -470,7 +474,10 @@
 update: 
 	@if [ -d .svn ]; then \
 		echo "Updating from Subversion..." ; \
+		fromrev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
 		svn update | tee update.out; \
+		torev="`svn info | $(AWK) '/Revision: / {print $$2}'`"; \
+		echo "`date`  Updated from revision $${fromrev} to $${torev}." >> update.log; \
 		rm -f .version; \
 		if [ `grep -c ^C update.out` -gt 0 ]; then \
 			echo ; echo "The following files have conflicts:" ; \

Modified: team/group/sip_session_timers/apps/app_directory.c
URL: http://svn.digium.com/view/asterisk/team/group/sip_session_timers/apps/app_directory.c?view=diff&rev=98976&r1=98975&r2=98976
==============================================================================
--- team/group/sip_session_timers/apps/app_directory.c (original)
+++ team/group/sip_session_timers/apps/app_directory.c Wed Jan 16 15:25:22 2008
@@ -88,9 +88,12 @@
 	OPT_SELECTFROMMENU =  (1 << 3),
 } directory_option_flags;
 
-struct items {
+struct directory_item {
 	char exten[AST_MAX_EXTENSION + 1];
 	char name[AST_MAX_EXTENSION + 1];
+	char key[50];				/* Text to order items. Either lastname+firstname or firstname+lastname */
+
+	AST_LIST_ENTRY(directory_item) entry;
 };
 
 AST_APP_OPTIONS(directory_app_options, {
@@ -215,73 +218,80 @@
 }
 #endif
 
-static char *convert(const char *lastname)
-{
-	char *tmp;
-	int lcount = 0;
-	tmp = ast_malloc(NUMDIGITS + 1);
-	if (tmp) {
-		while((*lastname > 32) && lcount < NUMDIGITS) {
-			switch(toupper(*lastname)) {
-			case '1':
-				tmp[lcount++] = '1';
-				break;
-			case '2':
-			case 'A':
-			case 'B':
-			case 'C':
-				tmp[lcount++] = '2';
-				break;
-			case '3':
-			case 'D':
-			case 'E':
-			case 'F':
-				tmp[lcount++] = '3';
-				break;
-			case '4':
-			case 'G':
-			case 'H':
-			case 'I':
-				tmp[lcount++] = '4';
-				break;
-			case '5':
-			case 'J':
-			case 'K':
-			case 'L':
-				tmp[lcount++] = '5';
-				break;
-			case '6':
-			case 'M':
-			case 'N':
-			case 'O':
-				tmp[lcount++] = '6';
-				break;
-			case '7':
-			case 'P':
-			case 'Q':
-			case 'R':
-			case 'S':
-				tmp[lcount++] = '7';
-				break;
-			case '8':
-			case 'T':
-			case 'U':
-			case 'V':
-				tmp[lcount++] = '8';
-				break;
-			case '9':
-			case 'W':
-			case 'X':
-			case 'Y':
-			case 'Z':
-				tmp[lcount++] = '9';
-				break;
-			}
-			lastname++;
-		}
-		tmp[lcount] = '\0';
-	}
-	return tmp;
+static int compare(const char *text, const char *template)
+{
+	char digit;
+
+	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;
+		}
+
+		if (*template++ != digit)
+			return -1;
+	}
+
+	return 0;
 }
 
 /* play name of mailbox owner.
@@ -333,85 +343,117 @@
 	return res;
 }
 
-static int get_mailbox_response(struct ast_channel *chan, const char *context, const char *dialcontext, const char *ext, const char *name, struct ast_flags *flags)
-{
-	int res = 0;
-	int loop = 3;
-
-	res = play_mailbox_owner(chan, context, ext, name, flags);
-	for (loop = 3 ; loop > 0; loop--) {
-		if (!res)
-			res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
-		if (!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);
+
+	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)) {
+		ast_log(LOG_WARNING,
+			"Can't find extension '%s' in context '%s'.  "
+			"Did you pass the wrong context to Directory?\n",
+			item->exten, dialcontext);
+		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)
+{
+	struct directory_item *item, **ptr;
+	int i, res, loop;
+
+	for (ptr = items, i = 0; i < count; i++, ptr++) {
+		item = *ptr;
+
+		for (loop = 3 ; loop > 0; loop--) {
+			res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
+
+			if (!res)
+				res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
+			if (!res)
+				res = ast_waitfordigit(chan, 3000);
+			ast_stopstream(chan);
+	
+			if (res == '1') {	/* Name selected */
+				return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1;
+			} else if (res == '*') {
+				/* Skip to next match in list */
+				break;
+			}
+
+			if (res < 0)
+				return -1;
+
+			res = 0;
+		}
+	}
+
+	/* Nothing was selected */
+	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)
+{
+	struct directory_item **block, *item;
+	int i, limit, res = 0;
+	char buf[9];
+
+	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)
+				res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
+			if (!res)
+				res = ast_waitstream(chan, AST_DIGIT_ANY);
+			if (!res)
+				res = ast_waitfordigit(chan, 800);
+		}
+
+		/* 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);
-		ast_stopstream(chan);
-	
-		if (res < 0) /* User hungup, so jump out now */
-			break;
-		if (res == '1') {	/* Name selected */
-			if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
-				/* We still want to set the exten though */
-				ast_copy_string(chan->exten, ext, sizeof(chan->exten));
-			} else {
-				if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
-					ast_log(LOG_WARNING,
-						"Can't find extension '%s' in context '%s'.  "
-						"Did you pass the wrong context to Directory?\n",
-						ext, dialcontext);
-					res = -1;
-				}
-			}
-			break;
-		}
-		if (res == '*') /* Skip to next match in list */
-			break;
-
-		/* Not '1', or '*', so decrement number of tries */
+		}
+
+		if (res && res > '0' && res < '1' + limit) {
+			return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1;
+		}
+
+		if (res < 0)
+			return -1;
+
 		res = 0;
 	}
 
-	return(res);
-}
-
-static int select_item(struct ast_channel *chan, const struct items *items, int itemcount, const char *context, const char *dialcontext, struct ast_flags *flags)
-{
-	int i, res = 0;
-	char buf[9];
-	for (i = 0; i < itemcount; i++) {
-		snprintf(buf, sizeof(buf), "digits/%d", i + 1);
-		/* Press <num> for <name>, [ extension <ext> ] */
-		res = ast_streamfile(chan, "dir-multi1", chan->language) ||
-			ast_waitstream(chan, AST_DIGIT_ANY) ||
-			ast_streamfile(chan, buf, chan->language) ||
-			ast_waitstream(chan, AST_DIGIT_ANY) ||
-			ast_streamfile(chan, "dir-multi2", chan->language) ||
-			ast_waitstream(chan, AST_DIGIT_ANY) ||
-			play_mailbox_owner(chan, context, items[i].exten, items[i].name, flags) ||
-			ast_waitstream(chan, AST_DIGIT_ANY) ||
-			ast_waitfordigit(chan, 800);
-		if (res)
-			break;
-	}
-	/* Press "9" for more names. */
-	if (!res)
-		res = ast_waitstream(chan, AST_DIGIT_ANY) ||
-			(itemcount == 8 && ast_streamfile(chan, "dir-multi9", chan->language)) ||
-			ast_waitstream(chan, AST_DIGIT_ANY) ||
-			ast_waitfordigit(chan, 3000);
-
-	if (res && res > '0' && res < '9') {
-		if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
-			/* We still want to set the exten */
-			ast_copy_string(chan->exten, items[res - '0'].exten, sizeof(chan->exten));
-		} else if (ast_goto_if_exists(chan, dialcontext, items[res - '1'].exten, 1)) {
-			ast_log(LOG_WARNING,
-				"Can't find extension '%s' in context '%s'.  "
-				"Did you pass the wrong context to Directory?\n",
-				items[res - '0'].exten, dialcontext);
-			res = -1;
-		}
-	}
-	return res;
+	/* Nothing was selected */
+	return 0;
 }
 
 static struct ast_config *realtime_directory(char *context)
@@ -473,18 +515,148 @@
 	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)
+{
+	struct directory_item *item;
+	const char *key = NULL;
+	int namelen;
+
+
+	/* 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;
+
+	/* Match */
+	item = ast_calloc(1, sizeof(*item));
+	if (!item)
+		return -1;
+	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;
+
+static int search_directory(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, int use_first_name, itemlist *alist)
+{
+	struct ast_variable *v;
+	char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
+	struct directory_item *item;
+	int res;
+
+	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, ",");
+
+		res = check_match(&item, pos, v->name, ext, use_first_name);
+		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)) {
+			const char *pos;
+			if (!strcasecmp(cat, "general"))
+				continue;
+			if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
+				continue;
+		
+			/* Find all candidate extensions */
+			pos = ast_variable_retrieve(ucfg, cat, "fullname");
+			if (!pos)
+				continue;
+
+			res = check_match(&item, pos, cat, ext, use_first_name);
+			if (!res)
+				continue;
+			else if (res < 0)
+				return -1;
+
+			AST_LIST_INSERT_TAIL(alist, item, entry);
+		}
+	}
+
+	return 0;
+}
+
+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);
+}
+
+static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
+{
+	if (!ast_goto_if_exists(chan, dialcontext, ext, 1) ||
+	    (!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;
+	}
+}
+
 static int do_directory(struct ast_channel *chan, struct ast_config *vmcfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, struct ast_flags *flags)
 {
 	/* Read in the first three digits..  "digit" is the first digit, already read */
-	char ext[NUMDIGITS + 1], *cat;
-	char name[80] = "";
-	struct ast_variable *v;
-	int res;
-	int found=0;
-	int lastuserchoice = 0;
-	char *start, *conv = NULL, *stringp = NULL;
-	char *pos;
-	int breakout = 0;
+	int res = 0;
+	itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+	struct directory_item *item, **ptr, **sorted = NULL;
+	int count, i;
+	char ext[NUMDIGITS + 1] = "";
 
 	if (ast_strlen_zero(context)) {
 		ast_log(LOG_WARNING,
@@ -492,263 +664,72 @@
 			"(context in which to interpret extensions)\n");
 		return -1;
 	}
-	if (digit == '0') {
-		if (!ast_goto_if_exists(chan, dialcontext, "o", 1) ||
-		    (!ast_strlen_zero(chan->macrocontext) &&
-		     !ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) {
-			return 0;
-		} else {
-			ast_log(LOG_WARNING, "Can't find extension 'o' in current context.  "
-				"Not Exiting the Directory!\n");
-			res = 0;
-		}
+
+	if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
+		return 0;
 	}	
-	if (digit == '*') {
-		if (!ast_goto_if_exists(chan, dialcontext, "a", 1) ||
-		    (!ast_strlen_zero(chan->macrocontext) &&
-		     !ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) {
-			return 0;
-		} else {
-			ast_log(LOG_WARNING, "Can't find extension 'a' in current context.  "
-				"Not Exiting the Directory!\n");
-			res = 0;
-		}
+
+	if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
+		return 0;
 	}	
-	memset(ext, 0, sizeof(ext));
+
 	ext[0] = digit;
-	res = 0;
-	if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1;
+	if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0)
+		return -1;
+
+	res = search_directory(context, vmcfg, ucfg, ext, ast_test_flag(flags, OPT_LISTBYFIRSTNAME), &alist);
+	if (res)
+		goto exit;
+
+	/* Count items in the list */
+	count = 0;
+	AST_LIST_TRAVERSE(&alist, item, entry) {
+		count++;
+	}
+
+	if (count < 1) {
+		res = ast_streamfile(chan, "dir-nomatch", chan->language);
+		goto exit;
+	}
+
+
+	/* Create plain array of pointers to items (for sorting) */
+	sorted = ast_calloc(count, sizeof(*sorted));
+
+	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++) {
+			ast_log(LOG_DEBUG, "%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);
+	} else {
+		/* Offer entries one by one */
+		res = select_item_seq(chan, sorted, count, context, dialcontext, flags);
+	}
+
 	if (!res) {
-		if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
-			char buf[AST_MAX_EXTENSION + 1], *bufptr, *fullname;
-			struct items menuitems[8];
-			int menucount = 0;
-			for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
-				if (strcasestr(v->value, "hidefromdir=yes") == NULL) {
-					ast_copy_string(buf, v->value, sizeof(buf));
-					bufptr = buf;
-					/* password,Full Name,email,pager,options */
-					strsep(&bufptr, ",");
-					pos = strsep(&bufptr, ",");
-					fullname = pos;
-
-					if (ast_test_flag(flags, OPT_LISTBYFIRSTNAME) && strrchr(pos, ' '))
-						pos = strrchr(pos, ' ') + 1;
-					conv = convert(pos);
-
-					if (conv && strcmp(conv, ext) == 0) {
-						/* Match */
-						found = 1;
-						ast_copy_string(menuitems[menucount].name, fullname, sizeof(menuitems[0].name));
-						ast_copy_string(menuitems[menucount].exten, v->name, sizeof(menuitems[0].exten));
-						menucount++;
-					}
-
-					if (menucount == 8) {
-						/* We have a full menu */
-						res = select_item(chan, menuitems, menucount, context, dialcontext, flags);
-						menucount = 0;
-						if (res != '9' && res != 0) {
-							if (res != -1)
-								lastuserchoice = res;
-							break;
-						}
-					}
-				}
-			}
-
-			if (menucount > 0) {
-				/* We have a partial menu left over */

[... 12664 lines stripped ...]



More information about the asterisk-commits mailing list