Asterisk - The Open Source Telephony Project  GIT-master-1f78ee9
Data Structures | Macros | Enumerations | Functions | Variables
app_directory.c File Reference

Provide a directory of extensions. More...

#include "asterisk.h"
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  directory_item
 
struct  itemlist
 

Macros

#define VOICEMAIL_CONFIG   "voicemail.conf"
 

Enumerations

enum  {
  OPT_LISTBYFIRSTNAME = (1 << 0), OPT_SAYEXTENSION = (1 << 1), OPT_FROMVOICEMAIL = (1 << 2), OPT_SELECTFROMMENU = (1 << 3),
  OPT_LISTBYLASTNAME = (1 << 4), OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME, OPT_PAUSE = (1 << 5), OPT_NOANSWER = (1 << 6),
  OPT_ALIAS = (1 << 7)
}
 
enum  {
  OPT_ARG_FIRSTNAME = 0, OPT_ARG_LASTNAME = 1, OPT_ARG_EITHER = 2, OPT_ARG_PAUSE = 3,
  OPT_ARG_ARRAY_SIZE = 4
}
 

Functions

static void __init_commonbuf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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)
 
static int compare (const char *text, const char *template)
 
static int directory_exec (struct ast_channel *chan, const char *data)
 
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[])
 
static int goto_exten (struct ast_channel *chan, const char *dialcontext, char *ext)
 
static int load_module (void)
 
static int play_mailbox_owner (struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)
 
static struct ast_configrealtime_directory (char *context)
 
static int search_directory (const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int search_directory_sub (const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
 
static int select_entry (struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
 
static int select_item_menu (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static int select_item_pause (struct ast_channel *chan, struct ast_flags *flags, char *opts[])
 
static int select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
 
static void sort_items (struct directory_item **sorted, int count)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const char app [] = "Directory"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
 
static const struct ast_app_option directory_app_options [128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, }
 

Detailed Description

Provide a directory of extensions.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file app_directory.c.

Macro Definition Documentation

◆ VOICEMAIL_CONFIG

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 144 of file app_directory.c.

Referenced by realtime_directory().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_LISTBYFIRSTNAME 
OPT_SAYEXTENSION 
OPT_FROMVOICEMAIL 
OPT_SELECTFROMMENU 
OPT_LISTBYLASTNAME 
OPT_LISTBYEITHER 
OPT_PAUSE 
OPT_NOANSWER 
OPT_ALIAS 

Definition at line 146 of file app_directory.c.

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_FIRSTNAME 
OPT_ARG_LASTNAME 
OPT_ARG_EITHER 
OPT_ARG_PAUSE 
OPT_ARG_ARRAY_SIZE 

Definition at line 158 of file app_directory.c.

158  {
159  OPT_ARG_FIRSTNAME = 0,
160  OPT_ARG_LASTNAME = 1,
161  OPT_ARG_EITHER = 2,
162  OPT_ARG_PAUSE = 3,
163  /* This *must* be the last value in this enum! */
164  OPT_ARG_ARRAY_SIZE = 4,
165 };

Function Documentation

◆ __init_commonbuf()

static void __init_commonbuf ( void  )
static

Definition at line 459 of file app_directory.c.

462 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 992 of file app_directory.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 992 of file app_directory.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 992 of file app_directory.c.

◆ check_match()

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 
)
static

Definition at line 559 of file app_directory.c.

References ast_calloc, ast_copy_string(), ast_debug, ast_strlen_zero, compare(), directory_item::context, directory_item::exten, item, directory_item::key, directory_item::name, and NULL.

Referenced by search_directory_sub().

560 {
561  struct directory_item *item;
562  const char *key = NULL;
563  int namelen;
564 
565  if (ast_strlen_zero(item_fullname)) {
566  return 0;
567  }
568 
569  /* Set key to last name or first name depending on search mode */
570  if (!use_first_name)
571  key = strchr(item_fullname, ' ');
572 
573  if (key)
574  key++;
575  else
576  key = item_fullname;
577 
578  if (compare(key, pattern_ext))
579  return 0;
580 
581  ast_debug(1, "Found match %s@%s\n", item_ext, item_context);
582 
583  /* Match */
584  item = ast_calloc(1, sizeof(*item));
585  if (!item)
586  return -1;
587  ast_copy_string(item->context, item_context, sizeof(item->context));
588  ast_copy_string(item->name, item_fullname, sizeof(item->name));
589  ast_copy_string(item->exten, item_ext, sizeof(item->exten));
590 
591  ast_copy_string(item->key, key, sizeof(item->key));
592  if (key != item_fullname) {
593  /* Key is the last name. Append first name to key in order to sort Last,First */
594  namelen = key - item_fullname - 1;
595  if (namelen > sizeof(item->key) - strlen(item->key) - 1)
596  namelen = sizeof(item->key) - strlen(item->key) - 1;
597  strncat(item->key, item_fullname, namelen);
598  }
599 
600  *result = item;
601  return 1;
602 }
static struct aco_type item
Definition: test_config.c:1463
#define NULL
Definition: resample.c:96
char context[AST_MAX_CONTEXT+1]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
char name[AST_MAX_EXTENSION+1]
#define ast_strlen_zero(a)
Definition: muted.c:73
char exten[AST_MAX_EXTENSION+1]
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
static int compare(const char *text, const char *template)

◆ compare()

static int compare ( const char *  text,
const char *  template 
)
static

Definition at line 188 of file app_directory.c.

References ast_strlen_zero, and digit.

Referenced by _ast_hashtab_create(), ast_sip_is_content_type(), and check_match().

189 {
190  char digit;
191 
192  if (ast_strlen_zero(text)) {
193  return -1;
194  }
195 
196  while (*template) {
197  digit = toupper(*text++);
198  switch (digit) {
199  case 0:
200  return -1;
201  case '1':
202  digit = '1';
203  break;
204  case '2':
205  case 'A':
206  case 'B':
207  case 'C':
208  digit = '2';
209  break;
210  case '3':
211  case 'D':
212  case 'E':
213  case 'F':
214  digit = '3';
215  break;
216  case '4':
217  case 'G':
218  case 'H':
219  case 'I':
220  digit = '4';
221  break;
222  case '5':
223  case 'J':
224  case 'K':
225  case 'L':
226  digit = '5';
227  break;
228  case '6':
229  case 'M':
230  case 'N':
231  case 'O':
232  digit = '6';
233  break;
234  case '7':
235  case 'P':
236  case 'Q':
237  case 'R':
238  case 'S':
239  digit = '7';
240  break;
241  case '8':
242  case 'T':
243  case 'U':
244  case 'V':
245  digit = '8';
246  break;
247  case '9':
248  case 'W':
249  case 'X':
250  case 'Y':
251  case 'Z':
252  digit = '9';
253  break;
254 
255  default:
256  if (digit > ' ')
257  return -1;
258  continue;
259  }
260 
261  if (*template++ != digit)
262  return -1;
263  }
264 
265  return 0;
266 }
char digit
char * text
Definition: app_queue.c:1511
#define ast_strlen_zero(a)
Definition: muted.c:73

◆ directory_exec()

static int directory_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 847 of file app_directory.c.

References args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_check_hangup(), ast_config_destroy(), ast_config_load, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_log, ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), CONFIG_STATUS_FILEINVALID, dialcontext, digit, directory_app_options, do_directory(), LOG_ERROR, NULL, OPT_ARG_ARRAY_SIZE, OPT_ARG_EITHER, OPT_ARG_FIRSTNAME, OPT_ARG_LASTNAME, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, OPT_NOANSWER, options, parse(), pbx_builtin_setvar_helper(), and realtime_directory().

Referenced by load_module().

848 {
849  int res = 0, digit = 3;
850  struct ast_config *cfg, *ucfg;
851  const char *dirintro;
852  char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, };
853  struct ast_flags flags = { 0 };
854  struct ast_flags config_flags = { 0 };
855  enum { FIRST, LAST, BOTH } which = LAST;
856  char digits[9] = "digits/3";
858  AST_APP_ARG(vmcontext);
861  );
862 
863  parse = ast_strdupa(data);
864 
865  AST_STANDARD_APP_ARGS(args, parse);
866 
867  if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
868  return -1;
869 
870  if (!(cfg = realtime_directory(args.vmcontext))) {
871  ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
872  return -1;
873  }
874 
875  if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) {
876  ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n");
877  ucfg = NULL;
878  }
879 
880  dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
881  if (ast_strlen_zero(dirintro))
882  dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
883  /* the above prompts probably should be modified to include 0 for dialing operator
884  and # for exiting (continues in dialplan) */
885 
887  if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) {
888  digit = atoi(opts[OPT_ARG_EITHER]);
889  }
890  which = BOTH;
891  } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
892  if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) {
893  digit = atoi(opts[OPT_ARG_FIRSTNAME]);
894  }
895  which = FIRST;
896  } else {
897  if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) {
898  digit = atoi(opts[OPT_ARG_LASTNAME]);
899  }
900  which = LAST;
901  }
902 
903  /* If no options specified, search by last name */
906  which = LAST;
907  }
908 
909  if (digit > 9) {
910  digit = 9;
911  } else if (digit < 1) {
912  digit = 3;
913  }
914  digits[7] = digit + '0';
915 
916  if (ast_channel_state(chan) != AST_STATE_UP) {
917  if (!ast_test_flag(&flags, OPT_NOANSWER)) {
918  /* Otherwise answer unless we're supposed to read while on-hook */
919  res = ast_answer(chan);
920  }
921  }
922  for (;;) {
923  if (!ast_strlen_zero(dirintro) && !res) {
924  res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
925  } else if (!res) {
926  /* Stop playing sounds as soon as we have a digit. */
927  res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY);
928  if (!res) {
929  res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY);
930  }
931  if (!res) {
932  res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY);
933  }
934  if (!res) {
935  res = ast_stream_and_wait(chan,
936  which == FIRST ? "dir-first" :
937  which == LAST ? "dir-last" :
938  "dir-firstlast", AST_DIGIT_ANY);
939  }
940  if (!res) {
941  res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY);
942  }
943  }
944  ast_stopstream(chan);
945  if (!res)
946  res = ast_waitfordigit(chan, 5000);
947 
948  if (res <= 0) {
949  if (res == 0) {
950  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "TIMEOUT");
951  }
952  break;
953  }
954 
955  res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts);
956  if (res)
957  break;
958 
959  res = ast_waitstream(chan, AST_DIGIT_ANY);
960  ast_stopstream(chan);
961  if (res < 0) {
962  break;
963  }
964  }
965 
966  if (ucfg)
967  ast_config_destroy(ucfg);
968  ast_config_destroy(cfg);
969 
970  if (ast_check_hangup(chan)) {
971  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "HANGUP");
972  } else if (res < 0) {
973  /* If the res < 0 and we didn't hangup, an unaccounted for error must have happened. */
974  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "FAILED");
975  }
976 
977  return res < 0 ? -1 : 0;
978 }
char digit
#define AST_DIGIT_ANY
Definition: file.h:48
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define CONFIG_STATUS_FILEINVALID
unsigned int flags
Definition: utils.h:200
ast_channel_state
ast_channel states
Definition: channelstate.h:35
const char * args
#define NULL
Definition: resample.c:96
static struct ast_config * realtime_directory(char *context)
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
static char dialcontext[AST_MAX_CONTEXT]
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2829
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:441
#define LOG_ERROR
Definition: logger.h:285
static const struct ast_app_option directory_app_options[128]
#define ast_strlen_zero(a)
Definition: muted.c:73
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1813
Structure used to handle boolean flags.
Definition: utils.h:199
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[])
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3150
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1775
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2780
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define AST_APP_ARG(name)
Define an application argument.

◆ do_directory()

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[] 
)
static

Definition at line 768 of file app_directory.c.

References ast_calloc, ast_channel_language(), ast_free, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log, ast_readstring(), ast_streamfile(), ast_test_flag, DEBUG_ATLEAST, digit, ext, directory_item::exten, goto_exten(), item, LOG_DEBUG, directory_item::name, NULL, OPT_SELECTFROMMENU, pbx_builtin_setvar_helper(), search_directory(), select_item_menu(), select_item_seq(), and sort_items().

Referenced by directory_exec().

769 {
770  /* Read in the first three digits.. "digit" is the first digit, already read */
771  int res = 0;
773  struct directory_item *item, **ptr, **sorted = NULL;
774  int count, i;
775  char ext[10] = "";
776 
777  if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
778  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
779  return digit;
780  }
781 
782  if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
783  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "ASSISTANT");
784  return digit;
785  }
786 
787  ext[0] = digit;
788  if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0)
789  return -1;
790 
791  res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist);
792  if (res)
793  goto exit;
794 
795  /* Count items in the list */
796  count = 0;
797  AST_LIST_TRAVERSE(&alist, item, entry) {
798  count++;
799  }
800 
801  if (count < 1) {
802  res = ast_streamfile(chan, "dir-nomatch", ast_channel_language(chan));
803  goto exit;
804  }
805 
806 
807  /* Create plain array of pointers to items (for sorting) */
808  sorted = ast_calloc(count, sizeof(*sorted));
809 
810  ptr = sorted;
811  AST_LIST_TRAVERSE(&alist, item, entry) {
812  *ptr++ = item;
813  }
814 
815  /* Sort items */
816  sort_items(sorted, count);
817 
818  if (DEBUG_ATLEAST(2)) {
819  ast_log(LOG_DEBUG, "Listing matching entries:\n");
820  for (ptr = sorted, i = 0; i < count; i++, ptr++) {
821  ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
822  }
823  }
824 
825  if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
826  /* Offer multiple entries at the same time */
827  res = select_item_menu(chan, sorted, count, dialcontext, flags, opts);
828  } else {
829  /* Offer entries one by one */
830  res = select_item_seq(chan, sorted, count, dialcontext, flags, opts);
831  }
832 
833  if (!res) {
834  res = ast_streamfile(chan, "dir-nomore", ast_channel_language(chan));
835  }
836 
837 exit:
838  if (sorted)
839  ast_free(sorted);
840 
841  while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
842  ast_free(item);
843 
844  return res;
845 }
char digit
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
static int select_item_seq(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
static struct aco_type item
Definition: test_config.c:1463
#define NULL
Definition: resample.c:96
#define LOG_DEBUG
Definition: logger.h:241
const char * ext
Definition: http.c:147
static void sort_items(struct directory_item **sorted, int count)
#define ast_log
Definition: astobj2.c:42
static char dialcontext[AST_MAX_CONTEXT]
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
Definition: f2c.h:128
static int search_directory(const char *context, struct ast_config *vmcfg, struct ast_config *ucfg, const char *ext, struct ast_flags flags, itemlist *alist)
static int select_item_menu(struct ast_channel *chan, struct directory_item **items, int count, const char *dialcontext, struct ast_flags *flags, char *opts[])
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
Definition: cdr_mysql.c:74
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
const char * ast_channel_language(const struct ast_channel *chan)
Definition: search.h:40
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders)
Reads multiple digits.
Definition: channel.c:6494
#define DEBUG_ATLEAST(level)
Definition: logger.h:433

◆ goto_exten()

static int goto_exten ( struct ast_channel chan,
const char *  dialcontext,
char *  ext 
)
static

Definition at line 268 of file app_directory.c.

References ast_channel_context(), ast_channel_macrocontext(), ast_goto_if_exists(), ast_log, ast_strlen_zero, LOG_WARNING, and S_OR.

Referenced by do_directory(), and select_item_seq().

269 {
270  if (!ast_goto_if_exists(chan, S_OR(dialcontext, ast_channel_context(chan)), ext, 1) ||
272  !ast_goto_if_exists(chan, ast_channel_macrocontext(chan), ext, 1))) {
273  return 0;
274  } else {
275  ast_log(LOG_WARNING, "Can't find extension '%s' in current context. "
276  "Not Exiting the Directory!\n", ext);
277  return -1;
278  }
279 }
#define LOG_WARNING
Definition: logger.h:274
const char * ext
Definition: http.c:147
#define ast_log
Definition: astobj2.c:42
static char dialcontext[AST_MAX_CONTEXT]
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8774
#define ast_strlen_zero(a)
Definition: muted.c:73
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_context(const struct ast_channel *chan)
const char * ast_channel_macrocontext(const struct ast_channel *chan)

◆ load_module()

static int load_module ( void  )
static

Definition at line 987 of file app_directory.c.

References app, ast_register_application_xml, and directory_exec().

988 {
990 }
static const char app[]
static int directory_exec(struct ast_channel *chan, const char *data)
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ play_mailbox_owner()

static int play_mailbox_owner ( struct ast_channel chan,
const char *  context,
const char *  ext,
const char *  name,
struct ast_flags flags 
)
static

Definition at line 286 of file app_directory.c.

References ast_alloca, ast_app_sayname(), ast_channel_language(), AST_DIGIT_ANY, AST_SAY_CASE_NONE, ast_say_character_str(), ast_stopstream(), ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, OPT_SAYEXTENSION, and S_OR.

Referenced by select_item_menu(), and select_item_seq().

288 {
289  int res = 0;
290  char *mailbox_id;
291 
292  mailbox_id = ast_alloca(strlen(ext) + strlen(context) + 2);
293  sprintf(mailbox_id, "%s@%s", ext, context); /* Safe */
294 
295  res = ast_app_sayname(chan, mailbox_id);
296  if (res >= 0) {
297  ast_stopstream(chan);
298  /* If Option 'e' was specified, also read the extension number with the name */
299  if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
300  ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
302  }
303  } else {
306  ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
308  }
309  }
310 
311  return res;
312 }
#define AST_DIGIT_ANY
Definition: file.h:48
int ast_app_sayname(struct ast_channel *chan, const char *mailbox_id)
Play a recorded user name for the mailbox to the specified channel.
Definition: main/app.c:710
#define ast_test_flag(p, flag)
Definition: utils.h:63
const char * ext
Definition: http.c:147
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang, enum ast_say_case_sensitivity sensitivity)
function to pronounce character and phonetic strings
Definition: channel.c:8200
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1813
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
const char * ast_channel_language(const struct ast_channel *chan)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187

◆ realtime_directory()

static struct ast_config* realtime_directory ( char *  context)
static

Definition at line 461 of file app_directory.c.

References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new_dynamic, ast_config_destroy(), ast_config_load, ast_debug, ast_load_realtime_multientry(), ast_log, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero, ast_true(), ast_variable_append(), ast_variable_browse(), ast_variable_new, ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, LOG_WARNING, mailbox, ast_variable::name, ast_variable::next, NULL, S_OR, SENTINEL, tmp(), ast_variable::value, var, and VOICEMAIL_CONFIG.

Referenced by directory_exec().

462 {
463  struct ast_config *cfg;
464  struct ast_config *rtdata = NULL;
465  struct ast_category *cat;
466  struct ast_variable *var;
467  char *category = NULL;
468  const char *fullname;
469  const char *hidefromdir, *searchcontexts = NULL;
470  struct ast_flags config_flags = { 0 };
471  struct ast_str *tmp = ast_str_thread_get(&commonbuf, 100);
472 
473  if (!tmp) {
474  return NULL;
475  }
476 
477  /* Load flat file config. */
478  cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
479 
480  if (!cfg) {
481  /* Loading config failed. */
482  ast_log(LOG_WARNING, "Loading config failed.\n");
483  return NULL;
484  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
485  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", VOICEMAIL_CONFIG);
486  return NULL;
487  }
488 
489  /* Get realtime entries, categorized by their mailbox number
490  and present in the requested context */
491  if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) {
492  if (ast_true(searchcontexts)) {
493  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL);
494  context = NULL;
495  } else {
496  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL);
497  context = "default";
498  }
499  } else if (!ast_strlen_zero(context)) {
500  rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
501  }
502 
503  /* if there are no results, just return the entries from the config file */
504  if (!rtdata) {
505  return cfg;
506  }
507 
508  while ((category = ast_category_browse(rtdata, category))) {
509  const char *mailbox = ast_variable_retrieve(rtdata, category, "mailbox");
510  const char *ctx = ast_variable_retrieve(rtdata, category, "context");
511 
512  if (ast_strlen_zero(mailbox)) {
513  ast_debug(3, "Skipping result with missing or empty mailbox\n");
514  continue;
515  }
516 
517  fullname = ast_variable_retrieve(rtdata, category, "fullname");
518  hidefromdir = ast_variable_retrieve(rtdata, category, "hidefromdir");
519  if (ast_true(hidefromdir)) {
520  /* Skip hidden */
521  continue;
522  }
523 
524  /* password,Full Name,email,pager,options */
525  ast_str_set(&tmp, 0, "no-password,%s,,,", S_OR(fullname, ""));
526  if (ast_variable_retrieve(rtdata, category, "alias")) {
527  struct ast_variable *alias;
528  for (alias = ast_variable_browse(rtdata, category); alias; alias = alias->next) {
529  if (!strcasecmp(alias->name, "alias")) {
530  ast_str_append(&tmp, 0, "|alias=%s", alias->value);
531  }
532  }
533  }
534 
535  /* Does the context exist within the config file? If not, make one */
536  if (!(cat = ast_category_get(cfg, ctx, NULL))) {
537  if (!(cat = ast_category_new_dynamic(ctx))) {
538  ast_log(LOG_WARNING, "Out of memory\n");
539  ast_config_destroy(cfg);
540  if (rtdata) {
541  ast_config_destroy(rtdata);
542  }
543  return NULL;
544  }
545  ast_category_append(cfg, cat);
546  }
547 
548  if ((var = ast_variable_new(mailbox, ast_str_buffer(tmp), ""))) {
549  ast_variable_append(cat, var);
550  } else {
551  ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
552  }
553  }
554  ast_config_destroy(rtdata);
555 
556  return cfg;
557 }
struct ast_variable * next
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define CONFIG_STATUS_FILEINVALID
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define SENTINEL
Definition: compiler.h:87
#define ast_config_load(filename, flags)
Load a config file.
Definition: term.c:57
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ast_variable_new(name, value, filename)
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3452
#define LOG_ERROR
Definition: logger.h:285
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1821
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_category_new_dynamic(name)
Create a category that is not backed by a file.
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_variable_append(struct ast_category *category, struct ast_variable *variable)
Definition: extconf.c:1178
void ast_category_append(struct ast_config *config, struct ast_category *cat)
Appends a category to a config.
Definition: extconf.c:2835
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define VOICEMAIL_CONFIG
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ast_category * ast_category_get(const struct ast_config *config, const char *category_name, const char *filter)
Retrieve a category if it exists.
Definition: main/config.c:1022

◆ search_directory()

static int search_directory ( const char *  context,
struct ast_config vmcfg,
struct ast_config ucfg,
const char *  ext,
struct ast_flags  flags,
itemlist alist 
)
static

Definition at line 717 of file app_directory.c.

References ast_category_browse(), ast_debug, ast_strlen_zero, ast_true(), ast_variable_retrieve(), NULL, and search_directory_sub().

Referenced by do_directory().

718 {
719  const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts");
720  if (ast_strlen_zero(context)) {
721  if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) {
722  /* Browse each context for a match */
723  int res;
724  const char *catg;
725  for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) {
726  if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) {
727  continue;
728  }
729 
730  if ((res = search_directory_sub(catg, vmcfg, ucfg, ext, flags, alist))) {
731  return res;
732  }
733  }
734  return 0;
735  } else {
736  ast_debug(1, "Searching by category default\n");
737  return search_directory_sub("default", vmcfg, ucfg, ext, flags, alist);
738  }
739  } else {
740  /* Browse only the listed context for a match */
741  ast_debug(1, "Searching by category %s\n", context);
742  return search_directory_sub(context, vmcfg, ucfg, ext, flags, alist);
743  }
744 }
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
const char * ext
Definition: http.c:147
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1821
#define ast_strlen_zero(a)
Definition: muted.c:73
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
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)
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116

◆ search_directory_sub()

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 
)
static

Definition at line 606 of file app_directory.c.

References a, ast_category_browse(), ast_config_option(), ast_debug, AST_LIST_INSERT_TAIL, ast_str_buffer(), ast_str_set(), ast_str_thread_get(), ast_strlen_zero, ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), item, ast_variable::name, directory_item::name, ast_variable::next, NULL, OPT_ALIAS, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, options, strcasestr(), strsep(), and ast_variable::value.

Referenced by search_directory().

607 {
608  struct ast_variable *v;
609  struct ast_str *buf = ast_str_thread_get(&commonbuf, 100);
610  char *name;
611  char *options;
612  char *alias;
613  char *cat;
614  struct directory_item *item;
615  int res;
616 
617  if (!buf) {
618  return -1;
619  }
620 
621  ast_debug(2, "Pattern: %s\n", ext);
622 
623  for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
624  ast_str_set(&buf, 0, "%s", v->value);
625  options = ast_str_buffer(buf);
626 
627  /* password,Full Name,email,pager,options */
628  strsep(&options, ","); /* Skip password */
629  name = strsep(&options, ","); /* Save full name */
630  strsep(&options, ","); /* Skip email */
631  strsep(&options, ","); /* Skip pager */
632  /* options is now the options field if it exists. */
633 
634  if (options && strcasestr(options, "hidefromdir=yes")) {
635  /* Ignore hidden */
636  continue;
637  }
638  if (ast_strlen_zero(name)) {
639  /* No name to compare against */
640  continue;
641  }
642 
643  res = 0;
644  if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
645  res = check_match(&item, context, name, v->name, ext, 0 /* use_first_name */);
646  }
647  if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
648  res = check_match(&item, context, name, v->name, ext, 1 /* use_first_name */);
649  }
650  if (!res && ast_test_flag(&flags, OPT_ALIAS)
651  && options && (alias = strcasestr(options, "alias="))) {
652  char *a;
653 
654  ast_debug(1, "Found alias: %s\n", alias);
655  while ((a = strsep(&alias, "|"))) {
656  if (!strncasecmp(a, "alias=", 6)) {
657  if ((res = check_match(&item, context, a + 6, v->name, ext, 1))) {
658  break;
659  }
660  }
661  }
662  }
663 
664  if (!res) {
665  continue;
666  } else if (res < 0) {
667  return -1;
668  }
669 
670  AST_LIST_INSERT_TAIL(alist, item, entry);
671  }
672 
673  if (ucfg) {
674  for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
675  const char *position;
676 
677  if (!strcasecmp(cat, "general")) {
678  continue;
679  }
680  if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) {
681  continue;
682  }
683 
684  /* Find all candidate extensions */
685  if (!(position = ast_variable_retrieve(ucfg, cat, "fullname"))) {
686  continue;
687  }
688 
689  res = 0;
690  if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
691  res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */);
692  }
693  if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
694  res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */);
695  }
696  if (!res && ast_test_flag(&flags, OPT_ALIAS)) {
697  for (v = ast_variable_browse(ucfg, cat); v; v = v->next) {
698  if (!strcasecmp(v->name, "alias")
699  && (res = check_match(&item, context, v->value, cat, ext, 1))) {
700  break;
701  }
702  }
703  }
704 
705  if (!res) {
706  continue;
707  } else if (res < 0) {
708  return -1;
709  }
710 
711  AST_LIST_INSERT_TAIL(alist, item, entry);
712  }
713  }
714  return 0;
715 }
struct ast_variable * next
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure for variables, used for configurations and for channel variables.
static struct aco_type item
Definition: test_config.c:1463
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
const char * ext
Definition: http.c:147
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
Definition: term.c:57
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)
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1821
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
char * strcasestr(const char *, const char *)
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
char * strsep(char **str, const char *delims)
const char * ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
Retrieve a configuration variable within the configuration set.
Definition: main/config.c:684
Definition: search.h:40
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
static struct test_options options
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static struct test_val a

◆ select_entry()

static int select_entry ( struct ast_channel chan,
const char *  dialcontext,
const struct directory_item item,
struct ast_flags flags 
)
static

Definition at line 314 of file app_directory.c.

References ast_channel_exten_set(), ast_debug, ast_goto_if_exists(), ast_log, ast_test_flag, directory_item::context, directory_item::exten, LOG_WARNING, directory_item::name, OPT_FROMVOICEMAIL, pbx_builtin_setvar_helper(), and S_OR.

Referenced by select_item_menu(), and select_item_seq().

315 {
316  ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context));
317 
318  if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
319  /* We still want to set the exten though */
320  ast_channel_exten_set(chan, item->exten);
321  } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) {
323  "Can't find extension '%s' in context '%s'. "
324  "Did you pass the wrong context to Directory?\n",
325  item->exten, S_OR(dialcontext, item->context));
326  return -1;
327  }
328 
329  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
330  return 0;
331 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:274
char context[AST_MAX_CONTEXT+1]
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
char name[AST_MAX_EXTENSION+1]
static char dialcontext[AST_MAX_CONTEXT]
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8774
char exten[AST_MAX_EXTENSION+1]
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79

◆ select_item_menu()

static int select_item_menu ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 395 of file app_directory.c.

References ast_channel_language(), AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, directory_item::context, directory_item::exten, item, directory_item::name, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

396 {
397  struct directory_item **block, *item;
398  int i, limit, res = 0;
399  char buf[9];
400 
401  /* option p(n): cellphone pause option */
402  select_item_pause(chan, flags, opts);
403 
404  for (block = items; count; block += limit, count -= limit) {
405  limit = count;
406  if (limit > 8)
407  limit = 8;
408 
409  for (i = 0; i < limit && !res; i++) {
410  item = block[i];
411 
412  snprintf(buf, sizeof(buf), "digits/%d", i + 1);
413  /* Press <num> for <name>, [ extension <ext> ] */
414  res = ast_streamfile(chan, "dir-multi1", ast_channel_language(chan));
415  if (!res)
416  res = ast_waitstream(chan, AST_DIGIT_ANY);
417  if (!res)
418  res = ast_streamfile(chan, buf, ast_channel_language(chan));
419  if (!res)
420  res = ast_waitstream(chan, AST_DIGIT_ANY);
421  if (!res)
422  res = ast_streamfile(chan, "dir-multi2", ast_channel_language(chan));
423  if (!res)
424  res = ast_waitstream(chan, AST_DIGIT_ANY);
425  if (!res)
426  res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
427  if (!res)
428  res = ast_waitstream(chan, AST_DIGIT_ANY);
429  if (!res)
430  res = ast_waitfordigit(chan, 800);
431  }
432 
433  /* Press "9" for more names. */
434  if (!res && count > limit) {
435  res = ast_streamfile(chan, "dir-multi9", ast_channel_language(chan));
436  if (!res)
437  res = ast_waitstream(chan, AST_DIGIT_ANY);
438  }
439 
440  if (!res) {
441  res = ast_waitfordigit(chan, 3000);
442  }
443 
444  if (res && res > '0' && res < '1' + limit) {
445  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "SELECTED");
446  return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1;
447  }
448 
449  if (res < 0)
450  return -1;
451 
452  res = 0;
453  }
454 
455  /* Nothing was selected */
456  return 0;
457 }
static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1250
#define AST_DIGIT_ANY
Definition: file.h:48
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct aco_type item
Definition: test_config.c:1463
char context[AST_MAX_CONTEXT+1]
static int select_item_pause(struct ast_channel *chan, struct ast_flags *flags, char *opts[])
char name[AST_MAX_EXTENSION+1]
static char dialcontext[AST_MAX_CONTEXT]
char exten[AST_MAX_EXTENSION+1]
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3150
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1775
const char * ast_channel_language(const struct ast_channel *chan)
static int play_mailbox_owner(struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)

◆ select_item_pause()

static int select_item_pause ( struct ast_channel chan,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 333 of file app_directory.c.

References ast_strlen_zero, ast_test_flag, ast_waitfordigit(), OPT_ARG_PAUSE, and OPT_PAUSE.

Referenced by select_item_menu(), and select_item_seq().

334 {
335  int res = 0, opt_pause = 0;
336 
337  if (ast_test_flag(flags, OPT_PAUSE) && !ast_strlen_zero(opts[OPT_ARG_PAUSE])) {
338  opt_pause = atoi(opts[OPT_ARG_PAUSE]);
339  if (opt_pause > 3000) {
340  opt_pause = 3000;
341  }
342  res = ast_waitfordigit(chan, opt_pause);
343  }
344  return res;
345 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_strlen_zero(a)
Definition: muted.c:73
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3150

◆ select_item_seq()

static int select_item_seq ( struct ast_channel chan,
struct directory_item **  items,
int  count,
const char *  dialcontext,
struct ast_flags flags,
char *  opts[] 
)
static

Definition at line 347 of file app_directory.c.

References AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_waitfordigit(), directory_item::context, directory_item::exten, goto_exten(), item, directory_item::name, pbx_builtin_setvar_helper(), play_mailbox_owner(), select_entry(), and select_item_pause().

Referenced by do_directory().

348 {
349  struct directory_item *item, **ptr;
350  int i, res, loop;
351 
352  /* option p(n): cellphone pause option */
353  /* allow early press of selection key */
354  res = select_item_pause(chan, flags, opts);
355 
356  for (ptr = items, i = 0; i < count; i++, ptr++) {
357  item = *ptr;
358 
359  for (loop = 3 ; loop > 0; loop--) {
360  if (!res)
361  res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags);
362  if (!res)
363  res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
364  if (!res)
365  res = ast_waitfordigit(chan, 3000);
366  ast_stopstream(chan);
367 
368  if (res == '0') { /* operator selected */
369  goto_exten(chan, dialcontext, "o");
370  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "OPERATOR");
371  return '0';
372  } else if (res == '1') { /* Name selected */
373  return select_entry(chan, dialcontext, item, flags) ? -1 : 1;
374  } else if (res == '*') {
375  /* Skip to next match in list */
376  break;
377  } else if (res == '#') {
378  /* Exit reading, continue in dialplan */
379  pbx_builtin_setvar_helper(chan, "DIRECTORY_RESULT", "USEREXIT");
380  return res;
381  }
382 
383  if (res < 0)
384  return -1;
385 
386  res = 0;
387  }
388  res = 0;
389  }
390 
391  /* Nothing was selected */
392  return 0;
393 }
static int select_entry(struct ast_channel *chan, const char *dialcontext, const struct directory_item *item, struct ast_flags *flags)
#define AST_DIGIT_ANY
Definition: file.h:48
static int goto_exten(struct ast_channel *chan, const char *dialcontext, char *ext)
static struct aco_type item
Definition: test_config.c:1463
char context[AST_MAX_CONTEXT+1]
static int select_item_pause(struct ast_channel *chan, struct ast_flags *flags, char *opts[])
char name[AST_MAX_EXTENSION+1]
static char dialcontext[AST_MAX_CONTEXT]
char exten[AST_MAX_EXTENSION+1]
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1813
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3150
static int play_mailbox_owner(struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags)
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187

◆ sort_items()

static void sort_items ( struct directory_item **  sorted,
int  count 
)
static

Definition at line 746 of file app_directory.c.

References directory_item::key, and tmp().

Referenced by do_directory().

747 {
748  int reordered, i;
749  struct directory_item **ptr, *tmp;
750 
751  if (count < 2)
752  return;
753 
754  /* Bubble-sort items by the key */
755  do {
756  reordered = 0;
757  for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
758  if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
759  tmp = ptr[0];
760  ptr[0] = ptr[1];
761  ptr[1] = tmp;
762  reordered++;
763  }
764  }
765  } while (reordered);
766 }
static int tmp()
Definition: bt_open.c:389

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 980 of file app_directory.c.

References app, and ast_unregister_application().

981 {
982  int res;
984  return res;
985 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static const char app[]

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Extension Directory" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 992 of file app_directory.c.

◆ app

const char app[] = "Directory"
static

Definition at line 139 of file app_directory.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 992 of file app_directory.c.

◆ commonbuf

struct ast_threadstorage commonbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_commonbuf , .custom_init = NULL , }
static

Definition at line 459 of file app_directory.c.

◆ directory_app_options

const struct ast_app_option directory_app_options[128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU }, [ 'n' ] = { .flag = OPT_NOANSWER }, [ 'a' ] = { .flag = OPT_ALIAS }, }
static

Definition at line 186 of file app_directory.c.

Referenced by directory_exec().