Tue Mar 2 17:32:04 2010

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"
Include dependency graph for app_directory.c:

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

static void __unreg_module ( void   )  [static]

Definition at line 783 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(), directory_item::exten, directory_item::key, and directory_item::name.

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 648 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(), dialcontext, directory_app_options, do_directory(), 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().

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

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 564 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, directory_item::entry, ext, directory_item::exten, goto_exten(), 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().

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

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

Definition at line 551 of file app_directory.c.

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

Referenced by do_directory().

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

static int load_module ( void   )  [static]

Definition at line 778 of file app_directory.c.

References ast_register_application, and directory_exec().

00779 {
00780    return ast_register_application(app, directory_exec, synopsis, descrip);
00781 }

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, 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, read]

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(), 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_strlen_zero(), 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       /* No name to compare against */
00477       if (ast_strlen_zero(pos)) {
00478          continue;
00479       }
00480 
00481       res = 0;
00482       if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00483          res = check_match(&item, pos, v->name, ext, 0 /* use_first_name */);
00484       }
00485       if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
00486          res = check_match(&item, pos, v->name, ext, 1 /* use_first_name */);
00487       }
00488 
00489       if (!res)
00490          continue;
00491       else if (res < 0)
00492          return -1;
00493 
00494       AST_LIST_INSERT_TAIL(alist, item, entry);
00495    }
00496 
00497    if (ucfg) {
00498       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
00499          const char *position;
00500          if (!strcasecmp(cat, "general"))
00501             continue;
00502          if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
00503             continue;
00504 
00505          /* Find all candidate extensions */
00506          position = ast_variable_retrieve(ucfg, cat, "fullname");
00507          if (!position)
00508             continue;
00509 
00510          res = 0;
00511          if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) {
00512             res = check_match(&item, position, cat, ext, 0 /* use_first_name */);
00513          }
00514          if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) {
00515             res = check_match(&item, position, cat, ext, 1 /* use_first_name */);
00516          }
00517 
00518          if (!res)
00519             continue;
00520          else if (res < 0)
00521             return -1;
00522 
00523          AST_LIST_INSERT_TAIL(alist, item, entry);
00524       }
00525    }
00526    return 0;
00527 }

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, 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, directory_item::exten, 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(), 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 529 of file app_directory.c.

References directory_item::key.

Referenced by do_directory().

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

static int unload_module ( void   )  [static]

Definition at line 771 of file app_directory.c.

References ast_unregister_application().

00772 {
00773    int res;
00774    res = ast_unregister_application(app);
00775    return res;
00776 }


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

char* app = "Directory" [static]

Definition at line 45 of file app_directory.c.

Definition at line 783 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 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1