Fri Jun 19 12:09:56 2009

Asterisk developer's documentation


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

Defines

#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)
}
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 __reg_module (void)
static void __unreg_module (void)
static int check_match (struct directory_item **result, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name)
static int compare (const char *text, const char *template)
static int directory_exec (struct ast_channel *chan, void *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)
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 select_entry (struct ast_channel *chan, const char *context, 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 *context, const char *dialcontext, struct ast_flags *flags)
static int select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, const char *context, const char *dialcontext, struct ast_flags *flags)
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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, }
static char * app = "Directory"
static struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static 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 },}
enum { ... }  directory_option_flags
static char * synopsis = "Provide directory of voicemail extensions"


Detailed Description

Provide a directory of extensions.

Author:
Mark Spencer <markster@digium.com>

Definition in file app_directory.c.


Define Documentation

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 91 of file app_directory.c.

Referenced by load_config(), realtime_directory(), and vm_change_password().


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_LISTBYFIRSTNAME 
OPT_SAYEXTENSION 
OPT_FROMVOICEMAIL 
OPT_SELECTFROMMENU 
OPT_LISTBYLASTNAME 
OPT_LISTBYEITHER 
OPT_PAUSE 

Definition at line 93 of file app_directory.c.

00093      {
00094    OPT_LISTBYFIRSTNAME = (1 << 0),
00095    OPT_SAYEXTENSION =    (1 << 1),
00096    OPT_FROMVOICEMAIL =   (1 << 2),
00097    OPT_SELECTFROMMENU =  (1 << 3),
00098    OPT_LISTBYLASTNAME =  (1 << 4),
00099    OPT_LISTBYEITHER =    OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME,
00100    OPT_PAUSE =           (1 << 5),
00101 } directory_option_flags;

anonymous enum

Enumerator:
OPT_ARG_FIRSTNAME 
OPT_ARG_LASTNAME 
OPT_ARG_EITHER 
OPT_ARG_PAUSE 
OPT_ARG_ARRAY_SIZE 

Definition at line 103 of file app_directory.c.

00103      {
00104    OPT_ARG_FIRSTNAME =   0,
00105    OPT_ARG_LASTNAME =    1,
00106    OPT_ARG_EITHER =      2,
00107    OPT_ARG_PAUSE =       3,
00108    /* This *must* be the last value in this enum! */
00109    OPT_ARG_ARRAY_SIZE =  4,
00110 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 778 of file app_directory.c.

static void __unreg_module ( void   )  [static]

Definition at line 778 of file app_directory.c.

static int check_match ( struct directory_item **  result,
const char *  item_fullname,
const char *  item_ext,
const char *  pattern_ext,
int  use_first_name 
) [static]

Definition at line 413 of file app_directory.c.

References ast_calloc, ast_copy_string(), compare(), and directory_item::key.

Referenced by search_directory().

00414 {
00415    struct directory_item *item;
00416    const char *key = NULL;
00417    int namelen;
00418 
00419 
00420    /* Set key to last name or first name depending on search mode */
00421    if (!use_first_name)
00422       key = strchr(item_fullname, ' ');
00423 
00424    if (key)
00425       key++;
00426    else
00427       key = item_fullname;
00428 
00429    if (compare(key, pattern_ext))
00430       return 0;
00431 
00432    /* Match */
00433    item = ast_calloc(1, sizeof(*item));
00434    if (!item)
00435       return -1;
00436    ast_copy_string(item->name, item_fullname, sizeof(item->name));
00437    ast_copy_string(item->exten, item_ext, sizeof(item->exten));
00438 
00439    ast_copy_string(item->key, key, sizeof(item->key));
00440    if (key != item_fullname) {
00441       /* Key is the last name. Append first name to key in order to sort Last,First */
00442       namelen = key - item_fullname - 1;
00443       if (namelen > sizeof(item->key) - strlen(item->key) - 1)
00444          namelen = sizeof(item->key) - strlen(item->key) - 1;
00445       strncat(item->key, item_fullname, namelen);
00446    }
00447 
00448    *result = item;
00449    return 1;
00450 }

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

Definition at line 130 of file app_directory.c.

References ast_strlen_zero().

Referenced by ast_hashtab_create(), and check_match().

00131 {
00132    char digit;
00133 
00134    if (ast_strlen_zero(text)) {
00135       return -1;
00136    }
00137 
00138    while (*template) {
00139       digit = toupper(*text++);
00140       switch (digit) {
00141       case 0:
00142          return -1;
00143       case '1':
00144          digit = '1';
00145          break;
00146       case '2':
00147       case 'A':
00148       case 'B':
00149       case 'C':
00150          digit = '2';
00151          break;
00152       case '3':
00153       case 'D':
00154       case 'E':
00155       case 'F':
00156          digit = '3';
00157          break;
00158       case '4':
00159       case 'G':
00160       case 'H':
00161       case 'I':
00162          digit = '4';
00163          break;
00164       case '5':
00165       case 'J':
00166       case 'K':
00167       case 'L':
00168          digit = '5';
00169          break;
00170       case '6':
00171       case 'M':
00172       case 'N':
00173       case 'O':
00174          digit = '6';
00175          break;
00176       case '7':
00177       case 'P':
00178       case 'Q':
00179       case 'R':
00180       case 'S':
00181          digit = '7';
00182          break;
00183       case '8':
00184       case 'T':
00185       case 'U':
00186       case 'V':
00187          digit = '8';
00188          break;
00189       case '9':
00190       case 'W':
00191       case 'X':
00192       case 'Y':
00193       case 'Z':
00194          digit = '9';
00195          break;
00196 
00197       default:
00198          if (digit > ' ')
00199             return -1;
00200          continue;
00201       }
00202 
00203       if (*template++ != digit)
00204          return -1;
00205    }
00206 
00207    return 0;
00208 }

static int directory_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 643 of file app_directory.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_parse_options(), 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(), chan, config_flags, dialcontext, directory_app_options, do_directory(), ast_flags::flags, LOG_ERROR, LOG_WARNING, OPT_ARG_ARRAY_SIZE, OPT_ARG_EITHER, OPT_ARG_FIRSTNAME, OPT_ARG_LASTNAME, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, parse(), and realtime_directory().

Referenced by load_module().

00644 {
00645    int res = 0, digit = 3;
00646    struct ast_config *cfg, *ucfg;
00647    const char *dirintro;
00648    char *parse, *opts[OPT_ARG_ARRAY_SIZE];
00649    struct ast_flags flags = { 0 };
00650    struct ast_flags config_flags = { 0 };
00651    enum { FIRST, LAST, BOTH } which = LAST;
00652    char digits[9] = "digits/3";
00653    AST_DECLARE_APP_ARGS(args,
00654       AST_APP_ARG(vmcontext);
00655       AST_APP_ARG(dialcontext);
00656       AST_APP_ARG(options);
00657    );
00658 
00659    if (ast_strlen_zero(data)) {
00660       ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
00661       return -1;
00662    }
00663 
00664    parse = ast_strdupa(data);
00665 
00666    AST_STANDARD_APP_ARGS(args, parse);
00667 
00668    if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
00669       return -1;
00670 
00671    if (ast_strlen_zero(args.dialcontext))
00672       args.dialcontext = args.vmcontext;
00673 
00674    cfg = realtime_directory(args.vmcontext);
00675    if (!cfg) {
00676       ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
00677       return -1;
00678    }
00679 
00680    ucfg = ast_config_load("users.conf", config_flags);
00681 
00682    dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
00683    if (ast_strlen_zero(dirintro))
00684       dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
00685 
00686    if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00687       if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) {
00688          digit = atoi(opts[OPT_ARG_EITHER]);
00689       }
00690       which = BOTH;
00691    } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
00692       if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) {
00693          digit = atoi(opts[OPT_ARG_FIRSTNAME]);
00694       }
00695       which = FIRST;
00696    } else {
00697       if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) {
00698          digit = atoi(opts[OPT_ARG_LASTNAME]);
00699       }
00700       which = LAST;
00701    }
00702 
00703    /* If no options specified, search by last name */
00704    if (!ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && !ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00705       ast_set_flag(&flags, OPT_LISTBYLASTNAME);
00706       which = LAST;
00707    }
00708 
00709    if (digit > 9) {
00710       digit = 9;
00711    } else if (digit < 1) {
00712       digit = 3;
00713    }
00714    digits[7] = digit + '0';
00715 
00716    if (chan->_state != AST_STATE_UP)
00717       res = ast_answer(chan);
00718 
00719    for (;;) {
00720       if (!ast_strlen_zero(dirintro) && !res) {
00721          res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
00722       } else if (!res) {
00723          /* Stop playing sounds as soon as we have a digit. */
00724          res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY);
00725          if (!res) {
00726             res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY);
00727          }
00728          if (!res) {
00729             res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY);
00730          }
00731          if (!res) {
00732             res = ast_stream_and_wait(chan, 
00733                which == FIRST ? "dir-first" :
00734                which == LAST ? "dir-last" :
00735                "dir-firstlast", AST_DIGIT_ANY);
00736          }
00737          if (!res) {
00738             ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY);
00739          }
00740       }
00741       ast_stopstream(chan);
00742       if (!res)
00743          res = ast_waitfordigit(chan, 5000);
00744 
00745       if (res <= 0)
00746          break;
00747 
00748       res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags);
00749       if (res)
00750          break;
00751 
00752       res = ast_waitstream(chan, AST_DIGIT_ANY);
00753       ast_stopstream(chan);
00754 
00755       if (res)
00756          break;
00757    }
00758 
00759    if (ucfg)
00760       ast_config_destroy(ucfg);
00761    ast_config_destroy(cfg);
00762 
00763    return res < 0 ? -1 : 0;
00764 }

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

Definition at line 559 of file app_directory.c.

References ast_calloc, ast_debug, ast_free, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_readstring(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, chan, directory_item::entry, ext, directory_item::exten, goto_exten(), ast_channel::language, LOG_DEBUG, LOG_WARNING, directory_item::name, OPT_SELECTFROMMENU, option_debug, search_directory(), select_item_menu(), select_item_seq(), and sort_items().

Referenced by directory_exec().

00560 {
00561    /* Read in the first three digits..  "digit" is the first digit, already read */
00562    int res = 0;
00563    itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
00564    struct directory_item *item, **ptr, **sorted = NULL;
00565    int count, i;
00566    char ext[10] = "";
00567 
00568    if (ast_strlen_zero(context)) {
00569       ast_log(LOG_WARNING,
00570          "Directory must be called with an argument "
00571          "(context in which to interpret extensions)\n");
00572       return -1;
00573    }
00574 
00575    if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
00576       return 0;
00577    }
00578 
00579    if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
00580       return 0;
00581    }
00582 
00583    ext[0] = digit;
00584    if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0)
00585       return -1;
00586 
00587    res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist);
00588    if (res)
00589       goto exit;
00590 
00591    /* Count items in the list */
00592    count = 0;
00593    AST_LIST_TRAVERSE(&alist, item, entry) {
00594       count++;
00595    }
00596 
00597    if (count < 1) {
00598       res = ast_streamfile(chan, "dir-nomatch", chan->language);
00599       goto exit;
00600    }
00601 
00602 
00603    /* Create plain array of pointers to items (for sorting) */
00604    sorted = ast_calloc(count, sizeof(*sorted));
00605 
00606    ptr = sorted;
00607    AST_LIST_TRAVERSE(&alist, item, entry) {
00608       *ptr++ = item;
00609    }
00610 
00611    /* Sort items */
00612    sort_items(sorted, count);
00613 
00614    if (option_debug) {
00615       ast_debug(2, "Listing matching entries:\n");
00616       for (ptr = sorted, i = 0; i < count; i++, ptr++) {
00617          ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
00618       }
00619    }
00620 
00621    if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
00622       /* Offer multiple entries at the same time */
00623       res = select_item_menu(chan, sorted, count, context, dialcontext, flags);
00624    } else {
00625       /* Offer entries one by one */
00626       res = select_item_seq(chan, sorted, count, context, dialcontext, flags);
00627    }
00628 
00629    if (!res) {
00630       res = ast_streamfile(chan, "dir-nomore", chan->language);
00631    }
00632 
00633 exit:
00634    if (sorted)
00635       ast_free(sorted);
00636 
00637    while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
00638       ast_free(item);
00639 
00640    return res;
00641 }

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

Definition at line 546 of file app_directory.c.

References ast_goto_if_exists(), ast_log(), ast_strlen_zero(), chan, LOG_WARNING, and ast_channel::macrocontext.

Referenced by do_directory().

00547 {
00548    if (!ast_goto_if_exists(chan, dialcontext, ext, 1) ||
00549       (!ast_strlen_zero(chan->macrocontext) &&
00550       !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) {
00551       return 0;
00552    } else {
00553       ast_log(LOG_WARNING, "Can't find extension '%s' in current context.  "
00554          "Not Exiting the Directory!\n", ext);
00555       return -1;
00556    }
00557 }

static int load_module ( void   )  [static]

Definition at line 773 of file app_directory.c.

References ast_register_application, and directory_exec().

00774 {
00775    return ast_register_application(app, directory_exec, synopsis, descrip);
00776 }

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 215 of file app_directory.c.

References ast_app_sayname(), AST_DIGIT_ANY, ast_say_character_str(), ast_stopstream(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, chan, ast_channel::language, OPT_SAYEXTENSION, and S_OR.

Referenced by select_item_menu(), and select_item_seq().

00217 {
00218    int res = 0;
00219    if ((res = ast_app_sayname(chan, ext, context)) >= 0) {
00220       ast_stopstream(chan);
00221       /* If Option 'e' was specified, also read the extension number with the name */
00222       if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
00223          ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
00224          res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
00225       }
00226    } else {
00227       res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language);
00228       if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) {
00229          ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
00230          res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
00231       }
00232    }
00233 
00234    return res;
00235 }

static struct ast_config* realtime_directory ( char *  context  )  [static]

Definition at line 350 of file app_directory.c.

References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new(), ast_config_destroy(), ast_config_load, ast_load_realtime_multientry(), ast_log(), ast_true(), ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), config_flags, LOG_WARNING, mailbox, S_OR, SENTINEL, var, and VOICEMAIL_CONFIG.

Referenced by directory_exec().

00351 {
00352    struct ast_config *cfg;
00353    struct ast_config *rtdata;
00354    struct ast_category *cat;
00355    struct ast_variable *var;
00356    char *mailbox;
00357    const char *fullname;
00358    const char *hidefromdir;
00359    char tmp[100];
00360    struct ast_flags config_flags = { 0 };
00361 
00362    /* Load flat file config. */
00363    cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
00364 
00365    if (!cfg) {
00366       /* Loading config failed. */
00367       ast_log(LOG_WARNING, "Loading config failed.\n");
00368       return NULL;
00369    }
00370 
00371    /* Get realtime entries, categorized by their mailbox number
00372       and present in the requested context */
00373    rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL);
00374 
00375    /* if there are no results, just return the entries from the config file */
00376    if (!rtdata)
00377       return cfg;
00378 
00379    /* Does the context exist within the config file? If not, make one */
00380    cat = ast_category_get(cfg, context);
00381    if (!cat) {
00382       cat = ast_category_new(context, "", 99999);
00383       if (!cat) {
00384          ast_log(LOG_WARNING, "Out of memory\n");
00385          ast_config_destroy(cfg);
00386          if (rtdata) {
00387             ast_config_destroy(rtdata);
00388          }
00389          return NULL;
00390       }
00391       ast_category_append(cfg, cat);
00392    }
00393 
00394    mailbox = NULL;
00395    while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
00396       fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
00397       if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) {
00398          /* Skip hidden */
00399          continue;
00400       }
00401       snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, ""));
00402       var = ast_variable_new(mailbox, tmp, "");
00403       if (var)
00404          ast_variable_append(cat, var);
00405       else
00406          ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
00407    }
00408    ast_config_destroy(rtdata);
00409 
00410    return cfg;
00411 }

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 454 of file app_directory.c.

References ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_MAX_EXTENSION, ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), directory_item::entry, ast_variable::name, ast_variable::next, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, strcasestr(), strsep(), and ast_variable::value.

Referenced by do_directory().

00455 {
00456    struct ast_variable *v;
00457    char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
00458    struct directory_item *item;
00459    int res;
00460 
00461    ast_debug(2, "Pattern: %s\n", ext);
00462 
00463    for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
00464 
00465       /* Ignore hidden */
00466       if (strcasestr(v->value, "hidefromdir=yes"))
00467          continue;
00468 
00469       ast_copy_string(buf, v->value, sizeof(buf));
00470       bufptr = buf;
00471 
00472       /* password,Full Name,email,pager,options */
00473       strsep(&bufptr, ",");
00474       pos = strsep(&bufptr, ",");
00475 
00476       res = 0;
00477       if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00478          res = check_match(&item, pos, v->name, ext, 0 /* use_first_name */);
00479       }
00480       if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
00481          res = check_match(&item, pos, v->name, ext, 1 /* use_first_name */);
00482       }
00483 
00484       if (!res)
00485          continue;
00486       else if (res < 0)
00487          return -1;
00488 
00489       AST_LIST_INSERT_TAIL(alist, item, entry);
00490    }
00491 
00492    if (ucfg) {
00493       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
00494          const char *position;
00495          if (!strcasecmp(cat, "general"))
00496             continue;
00497          if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
00498             continue;
00499 
00500          /* Find all candidate extensions */
00501          position = ast_variable_retrieve(ucfg, cat, "fullname");
00502          if (!position)
00503             continue;
00504 
00505          res = 0;
00506          if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00507             res = check_match(&item, position, cat, ext, 0 /* use_first_name */);
00508          }
00509          if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
00510             res = check_match(&item, position, cat, ext, 1 /* use_first_name */);
00511          }
00512 
00513          if (!res)
00514             continue;
00515          else if (res < 0)
00516             return -1;
00517 
00518          AST_LIST_INSERT_TAIL(alist, item, entry);
00519       }
00520    }
00521    return 0;
00522 }

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

Definition at line 237 of file app_directory.c.

References ast_copy_string(), ast_debug, ast_goto_if_exists(), ast_log(), ast_test_flag, chan, ast_channel::exten, directory_item::exten, LOG_WARNING, directory_item::name, and OPT_FROMVOICEMAIL.

Referenced by select_item_menu(), and select_item_seq().

00238 {
00239    ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, dialcontext);
00240 
00241    if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
00242       /* We still want to set the exten though */
00243       ast_copy_string(chan->exten, item->exten, sizeof(chan->exten));
00244    } else if (ast_goto_if_exists(chan, dialcontext, item->exten, 1)) {
00245       ast_log(LOG_WARNING,
00246          "Can't find extension '%s' in context '%s'.  "
00247          "Did you pass the wrong context to Directory?\n",
00248          item->exten, dialcontext);
00249       return -1;
00250    }
00251 
00252    return 0;
00253 }

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

Definition at line 290 of file app_directory.c.

References AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, chan, directory_item::exten, ast_channel::language, directory_item::name, play_mailbox_owner(), and select_entry().

Referenced by do_directory().

00291 {
00292    struct directory_item **block, *item;
00293    int i, limit, res = 0;
00294    char buf[9];
00295 
00296    for (block = items; count; block += limit, count -= limit) {
00297       limit = count;
00298       if (limit > 8)
00299          limit = 8;
00300 
00301       for (i = 0; i < limit && !res; i++) {
00302          item = block[i];
00303 
00304          snprintf(buf, sizeof(buf), "digits/%d", i + 1);
00305          /* Press <num> for <name>, [ extension <ext> ] */
00306          res = ast_streamfile(chan, "dir-multi1", chan->language);
00307          if (!res)
00308             res = ast_waitstream(chan, AST_DIGIT_ANY);
00309          if (!res)
00310             res = ast_streamfile(chan, buf, chan->language);
00311          if (!res)
00312             res = ast_waitstream(chan, AST_DIGIT_ANY);
00313          if (!res)
00314             res = ast_streamfile(chan, "dir-multi2", chan->language);
00315          if (!res)
00316             res = ast_waitstream(chan, AST_DIGIT_ANY);
00317          if (!res)
00318             res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
00319          if (!res)
00320             res = ast_waitstream(chan, AST_DIGIT_ANY);
00321          if (!res)
00322             res = ast_waitfordigit(chan, 800);
00323       }
00324 
00325       /* Press "9" for more names. */
00326       if (!res && count > limit) {
00327          res = ast_streamfile(chan, "dir-multi9", chan->language);
00328          if (!res)
00329             res = ast_waitstream(chan, AST_DIGIT_ANY);
00330       }
00331 
00332       if (!res) {
00333          res = ast_waitfordigit(chan, 3000);
00334       }
00335 
00336       if (res && res > '0' && res < '1' + limit) {
00337          return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1;
00338       }
00339 
00340       if (res < 0)
00341          return -1;
00342 
00343       res = 0;
00344    }
00345 
00346    /* Nothing was selected */
00347    return 0;
00348 }

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

Definition at line 255 of file app_directory.c.

References AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_waitfordigit(), chan, directory_item::exten, directory_item::name, play_mailbox_owner(), and select_entry().

Referenced by do_directory().

00256 {
00257    struct directory_item *item, **ptr;
00258    int i, res, loop;
00259 
00260    for (ptr = items, i = 0; i < count; i++, ptr++) {
00261       item = *ptr;
00262 
00263       for (loop = 3 ; loop > 0; loop--) {
00264          res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
00265 
00266          if (!res)
00267             res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
00268          if (!res)
00269             res = ast_waitfordigit(chan, 3000);
00270          ast_stopstream(chan);
00271    
00272          if (res == '1') { /* Name selected */
00273             return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1;
00274          } else if (res == '*') {
00275             /* Skip to next match in list */
00276             break;
00277          }
00278 
00279          if (res < 0)
00280             return -1;
00281 
00282          res = 0;
00283       }
00284    }
00285 
00286    /* Nothing was selected */
00287    return 0;
00288 }

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

Definition at line 524 of file app_directory.c.

References directory_item::key.

Referenced by do_directory().

00525 {
00526    int reordered, i;
00527    struct directory_item **ptr, *tmp;
00528 
00529    if (count < 2)
00530       return;
00531 
00532    /* Bubble-sort items by the key */
00533    do {
00534       reordered = 0;
00535       for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
00536          if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
00537             tmp = ptr[0];
00538             ptr[0] = ptr[1];
00539             ptr[1] = tmp;
00540             reordered++;
00541          }
00542       }
00543    } while (reordered);
00544 }

static int unload_module ( void   )  [static]

Definition at line 766 of file app_directory.c.

References ast_unregister_application().

00767 {
00768    int res;
00769    res = ast_unregister_application(app);
00770    return res;
00771 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 778 of file app_directory.c.

char* app = "Directory" [static]

Definition at line 45 of file app_directory.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 778 of file app_directory.c.

char* descrip [static]

Definition at line 48 of file app_directory.c.

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 },} [static]

Definition at line 128 of file app_directory.c.

Referenced by directory_exec().

enum { ... } directory_option_flags

char* synopsis = "Provide directory of voicemail extensions" [static]

Definition at line 47 of file app_directory.c.


Generated on Fri Jun 19 12:09:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7