Thu Jul 9 13:40:44 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"

Go to the source code of this file.

Data Structures

struct  directory_item
struct  itemlist

Defines

#define NUMDIGITS   3
#define VOICEMAIL_CONFIG   "voicemail.conf"

Enumerations

enum  { OPT_LISTBYFIRSTNAME = (1 << 0), OPT_SAYEXTENSION = (1 << 1), OPT_FROMVOICEMAIL = (1 << 2), OPT_SELECTFROMMENU = (1 << 3) }

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, 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, int use_first_name, 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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static char * app = "Directory"
static const struct ast_module_infoast_module_info = &__mod_info
static char * descrip
static struct ast_app_option directory_app_options [128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME }, [ '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 NUMDIGITS   3

Definition at line 82 of file app_directory.c.

Referenced by do_directory().

#define VOICEMAIL_CONFIG   "voicemail.conf"

Definition at line 79 of file app_directory.c.

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


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_LISTBYFIRSTNAME 
OPT_SAYEXTENSION 
OPT_FROMVOICEMAIL 
OPT_SELECTFROMMENU 

Definition at line 84 of file app_directory.c.

00084      {
00085    OPT_LISTBYFIRSTNAME = (1 << 0),
00086    OPT_SAYEXTENSION =    (1 << 1),
00087    OPT_FROMVOICEMAIL =   (1 << 2),
00088    OPT_SELECTFROMMENU =  (1 << 3),
00089 } directory_option_flags;


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 849 of file app_directory.c.

static void __unreg_module ( void   )  [static]

Definition at line 849 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 525 of file app_directory.c.

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

Referenced by search_directory().

00526 {
00527    struct directory_item *item;
00528    const char *key = NULL;
00529    int namelen;
00530 
00531 
00532    /* Set key to last name or first name depending on search mode */
00533    if (!use_first_name)
00534       key = strchr(item_fullname, ' ');
00535 
00536    if (key)
00537       key++;
00538    else
00539       key = item_fullname;
00540 
00541    if (compare(key, pattern_ext))
00542       return 0;
00543 
00544    /* Match */
00545    item = ast_calloc(1, sizeof(*item));
00546    if (!item)
00547       return -1;
00548    ast_copy_string(item->name, item_fullname, sizeof(item->name));
00549    ast_copy_string(item->exten, item_ext, sizeof(item->exten));
00550 
00551    ast_copy_string(item->key, key, sizeof(item->key));
00552    if (key != item_fullname) {
00553       /* Key is the last name. Append first name to key in order to sort Last,First */
00554       namelen = key - item_fullname - 1;
00555       if (namelen > sizeof(item->key) - strlen(item->key) - 1)
00556          namelen = sizeof(item->key) - strlen(item->key) - 1;
00557       strncat(item->key, item_fullname, namelen);
00558    }
00559 
00560    *result = item;
00561    return 1;
00562 }

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

Definition at line 221 of file app_directory.c.

References ast_strlen_zero().

Referenced by check_match().

00222 {
00223    char digit;
00224 
00225    if (ast_strlen_zero(text)) {
00226       return -1;
00227    }
00228 
00229    while (*template) {
00230       digit = toupper(*text++);
00231       switch (digit) {
00232       case 0:
00233          return -1;
00234       case '1':
00235          digit = '1';
00236          break;
00237       case '2':
00238       case 'A':
00239       case 'B':
00240       case 'C':
00241          digit = '2';
00242          break;
00243       case '3':
00244       case 'D':
00245       case 'E':
00246       case 'F':
00247          digit = '3';
00248          break;
00249       case '4':
00250       case 'G':
00251       case 'H':
00252       case 'I':
00253          digit = '4';
00254          break;
00255       case '5':
00256       case 'J':
00257       case 'K':
00258       case 'L':
00259          digit = '5';
00260          break;
00261       case '6':
00262       case 'M':
00263       case 'N':
00264       case 'O':
00265          digit = '6';
00266          break;
00267       case '7':
00268       case 'P':
00269       case 'Q':
00270       case 'R':
00271       case 'S':
00272          digit = '7';
00273          break;
00274       case '8':
00275       case 'T':
00276       case 'U':
00277       case 'V':
00278          digit = '8';
00279          break;
00280       case '9':
00281       case 'W':
00282       case 'X':
00283       case 'Y':
00284       case 'Z':
00285          digit = '9';
00286          break;
00287 
00288       default:
00289          if (digit > ' ')
00290             return -1;
00291          continue;
00292       }
00293 
00294       if (*template++ != digit)
00295          return -1;
00296    }
00297 
00298    return 0;
00299 }

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

Definition at line 743 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_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, dialcontext, directory_app_options, do_directory(), ast_flags::flags, LOG_ERROR, LOG_WARNING, OPT_LISTBYFIRSTNAME, parse(), and realtime_directory().

Referenced by load_module().

00744 {
00745    int res = 0;
00746    struct ast_config *cfg, *ucfg;
00747    const char *dirintro;
00748    char *parse, *opts[0];
00749    struct ast_flags flags = { 0 };
00750    struct ast_flags config_flags = { 0 };
00751    AST_DECLARE_APP_ARGS(args,
00752       AST_APP_ARG(vmcontext);
00753       AST_APP_ARG(dialcontext);
00754       AST_APP_ARG(options);
00755    );
00756 
00757    if (ast_strlen_zero(data)) {
00758       ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
00759       return -1;
00760    }
00761 
00762    parse = ast_strdupa(data);
00763 
00764    AST_STANDARD_APP_ARGS(args, parse);
00765 
00766    if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options))
00767       return -1;
00768 
00769    if (ast_strlen_zero(args.dialcontext))
00770       args.dialcontext = args.vmcontext;
00771 
00772    cfg = realtime_directory(args.vmcontext);
00773    if (!cfg) {
00774       ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
00775       return -1;
00776    }
00777 
00778    ucfg = ast_config_load("users.conf", config_flags);
00779 
00780    dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
00781    if (ast_strlen_zero(dirintro))
00782       dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
00783    if (ast_strlen_zero(dirintro))
00784       dirintro = ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) ? "dir-intro-fn" : "dir-intro";
00785 
00786    if (chan->_state != AST_STATE_UP)
00787       res = ast_answer(chan);
00788 
00789    for (;;) {
00790       if (!res)
00791          res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY);
00792       ast_stopstream(chan);
00793       if (!res)
00794          res = ast_waitfordigit(chan, 5000);
00795 
00796       if (res <= 0)
00797          break;
00798 
00799       res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, &flags);
00800       if (res)
00801          break;
00802 
00803       res = ast_waitstream(chan, AST_DIGIT_ANY);
00804       ast_stopstream(chan);
00805 
00806       if (res)
00807          break;
00808    }
00809 
00810    if (ucfg)
00811       ast_config_destroy(ucfg);
00812    ast_config_destroy(cfg);
00813 
00814    return res < 0 ? -1 : 0;
00815 }

static int do_directory ( struct ast_channel chan,
struct ast_config vmcfg,
struct ast_config ucfg,
char *  context,
char *  dialcontext,
char  digit,
struct ast_flags flags 
) [static]

Definition at line 659 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, NUMDIGITS, OPT_LISTBYFIRSTNAME, OPT_SELECTFROMMENU, option_debug, search_directory(), select_item_menu(), select_item_seq(), and sort_items().

Referenced by directory_exec().

00660 {
00661    /* Read in the first three digits..  "digit" is the first digit, already read */
00662    int res = 0;
00663    itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
00664    struct directory_item *item, **ptr, **sorted = NULL;
00665    int count, i;
00666    char ext[NUMDIGITS + 1] = "";
00667 
00668    if (ast_strlen_zero(context)) {
00669       ast_log(LOG_WARNING,
00670          "Directory must be called with an argument "
00671          "(context in which to interpret extensions)\n");
00672       return -1;
00673    }
00674 
00675    if (digit == '0' && !goto_exten(chan, dialcontext, "o")) {
00676       return 0;
00677    }
00678 
00679    if (digit == '*' && !goto_exten(chan, dialcontext, "a")) {
00680       return 0;
00681    }
00682 
00683    ext[0] = digit;
00684    if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0)
00685       return -1;
00686 
00687    res = search_directory(context, vmcfg, ucfg, ext, ast_test_flag(flags, OPT_LISTBYFIRSTNAME), &alist);
00688    if (res)
00689       goto exit;
00690 
00691    /* Count items in the list */
00692    count = 0;
00693    AST_LIST_TRAVERSE(&alist, item, entry) {
00694       count++;
00695    }
00696 
00697    if (count < 1) {
00698       res = ast_streamfile(chan, "dir-nomatch", chan->language);
00699       goto exit;
00700    }
00701 
00702 
00703    /* Create plain array of pointers to items (for sorting) */
00704    sorted = ast_calloc(count, sizeof(*sorted));
00705 
00706    ptr = sorted;
00707    AST_LIST_TRAVERSE(&alist, item, entry) {
00708       *ptr++ = item;
00709    }
00710 
00711    /* Sort items */
00712    sort_items(sorted, count);
00713 
00714    if (option_debug) {
00715       ast_debug(2, "Listing matching entries:\n");
00716       for (ptr = sorted, i = 0; i < count; i++, ptr++) {
00717          ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name);
00718       }
00719    }
00720 
00721    if (ast_test_flag(flags, OPT_SELECTFROMMENU)) {
00722       /* Offer multiple entries at the same time */
00723       res = select_item_menu(chan, sorted, count, context, dialcontext, flags);
00724    } else {
00725       /* Offer entries one by one */
00726       res = select_item_seq(chan, sorted, count, context, dialcontext, flags);
00727    }
00728 
00729    if (!res) {
00730       res = ast_streamfile(chan, "dir-nomore", chan->language);
00731    }
00732 
00733 exit:
00734    if (sorted)
00735       ast_free(sorted);
00736 
00737    while ((item = AST_LIST_REMOVE_HEAD(&alist, entry)))
00738       ast_free(item);
00739 
00740    return res;
00741 }

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

Definition at line 646 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().

00647 {
00648    if (!ast_goto_if_exists(chan, dialcontext, ext, 1) ||
00649       (!ast_strlen_zero(chan->macrocontext) &&
00650       !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) {
00651       return 0;
00652    } else {
00653       ast_log(LOG_WARNING, "Can't find extension '%s' in current context.  "
00654          "Not Exiting the Directory!\n", ext);
00655       return -1;
00656    }
00657 }

static int load_module ( void   )  [static]

Definition at line 824 of file app_directory.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log(), ast_register_application, ast_variable_retrieve(), directory_exec(), LOG_WARNING, and VOICEMAIL_CONFIG.

00825 {
00826 #ifdef ODBC_STORAGE
00827    struct ast_flags config_flags = { 0 };
00828    struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
00829    const char *tmp;
00830 
00831    if (cfg) {
00832       if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
00833          ast_copy_string(odbc_database, tmp, sizeof(odbc_database));
00834       }
00835       if ((tmp = ast_variable_retrieve(cfg, "general", "odbctable"))) {
00836          ast_copy_string(odbc_table, tmp, sizeof(odbc_table));
00837       }
00838       if ((tmp = ast_variable_retrieve(cfg, "general", "format"))) {
00839          ast_copy_string(vmfmts, tmp, sizeof(vmfmts));
00840       }
00841       ast_config_destroy(cfg);
00842    } else
00843       ast_log(LOG_WARNING, "Unable to load " VOICEMAIL_CONFIG " - ODBC defaults will be used\n");
00844 #endif
00845 
00846    return ast_register_application(app, directory_exec, synopsis, descrip);
00847 }

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

References ast_config_AST_SPOOL_DIR, AST_DIGIT_ANY, ast_filedelete(), ast_fileexists(), 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().

00308 {
00309    int res = 0;
00310    char fn[256];
00311 
00312    /* Check for the VoiceMail2 greeting first */
00313    snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
00314       ast_config_AST_SPOOL_DIR, context, ext);
00315 #ifdef ODBC_STORAGE
00316    retrieve_file(fn);
00317 #endif
00318 
00319    if (ast_fileexists(fn, NULL, chan->language) <= 0) {
00320       /* no file, check for an old-style Voicemail greeting */
00321       snprintf(fn, sizeof(fn), "%s/vm/%s/greet",
00322          ast_config_AST_SPOOL_DIR, ext);
00323    }
00324 #ifdef ODBC_STORAGE
00325    retrieve_file(fn);
00326 #endif
00327 
00328    if (ast_fileexists(fn, NULL, chan->language) > 0) {
00329       res = ast_stream_and_wait(chan, fn, AST_DIGIT_ANY);
00330       ast_stopstream(chan);
00331       /* If Option 'e' was specified, also read the extension number with the name */
00332       if (ast_test_flag(flags, OPT_SAYEXTENSION)) {
00333          ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
00334          res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
00335       }
00336    } else {
00337       res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language);
00338       if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) {
00339          ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY);
00340          res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
00341       }
00342    }
00343 #ifdef ODBC_STORAGE
00344    ast_filedelete(fn, NULL);
00345 #endif
00346 
00347    return res;
00348 }

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

Definition at line 463 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_variable_append(), ast_variable_new(), ast_variable_retrieve(), LOG_WARNING, mailbox, var, and VOICEMAIL_CONFIG.

Referenced by directory_exec().

00464 {
00465    struct ast_config *cfg;
00466    struct ast_config *rtdata;
00467    struct ast_category *cat;
00468    struct ast_variable *var;
00469    char *mailbox;
00470    const char *fullname;
00471    const char *hidefromdir;
00472    char tmp[100];
00473    struct ast_flags config_flags = { 0 };
00474 
00475    /* Load flat file config. */
00476    cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags);
00477 
00478    if (!cfg) {
00479       /* Loading config failed. */
00480       ast_log(LOG_WARNING, "Loading config failed.\n");
00481       return NULL;
00482    }
00483 
00484    /* Get realtime entries, categorized by their mailbox number
00485       and present in the requested context */
00486    rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL);
00487 
00488    /* if there are no results, just return the entries from the config file */
00489    if (!rtdata)
00490       return cfg;
00491 
00492    /* Does the context exist within the config file? If not, make one */
00493    cat = ast_category_get(cfg, context);
00494    if (!cat) {
00495       cat = ast_category_new(context, "", 99999);
00496       if (!cat) {
00497          ast_log(LOG_WARNING, "Out of memory\n");
00498          ast_config_destroy(cfg);
00499          if (rtdata) {
00500             ast_config_destroy(rtdata);
00501          }
00502          return NULL;
00503       }
00504       ast_category_append(cfg, cat);
00505    }
00506 
00507    mailbox = NULL;
00508    while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
00509       fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
00510       hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir");
00511       snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s",
00512          fullname ? fullname : "",
00513          hidefromdir ? hidefromdir : "no");
00514       var = ast_variable_new(mailbox, tmp, "");
00515       if (var)
00516          ast_variable_append(cat, var);
00517       else
00518          ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
00519    }
00520    ast_config_destroy(rtdata);
00521 
00522    return cfg;
00523 }

static int search_directory ( const char *  context,
struct ast_config vmcfg,
struct ast_config ucfg,
const char *  ext,
int  use_first_name,
itemlist alist 
) [static]

Definition at line 566 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_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), directory_item::entry, ast_variable::name, ast_variable::next, S_OR, strcasestr(), strsep(), and ast_variable::value.

Referenced by do_directory().

00567 {
00568    struct ast_variable *v;
00569    char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat;
00570    struct directory_item *item;
00571    int res;
00572 
00573    ast_debug(2, "Pattern: %s\n", ext);
00574 
00575    for (v = ast_variable_browse(vmcfg, context); v; v = v->next) {
00576 
00577       /* Ignore hidden */
00578       if (strcasestr(v->value, "hidefromdir=yes"))
00579          continue;
00580 
00581       ast_copy_string(buf, v->value, sizeof(buf));
00582       bufptr = buf;
00583 
00584       /* password,Full Name,email,pager,options */
00585       strsep(&bufptr, ",");
00586       pos = strsep(&bufptr, ",");
00587 
00588       res = check_match(&item, S_OR(pos, ""), v->name, ext, use_first_name);
00589       if (!res)
00590          continue;
00591       else if (res < 0)
00592          return -1;
00593 
00594       AST_LIST_INSERT_TAIL(alist, item, entry);
00595    }
00596 
00597 
00598    if (ucfg) {
00599       for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
00600          const char *pos;
00601          if (!strcasecmp(cat, "general"))
00602             continue;
00603          if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
00604             continue;
00605 
00606          /* Find all candidate extensions */
00607          pos = ast_variable_retrieve(ucfg, cat, "fullname");
00608          if (!pos)
00609             continue;
00610 
00611          res = check_match(&item, pos, cat, ext, use_first_name);
00612          if (!res)
00613             continue;
00614          else if (res < 0)
00615             return -1;
00616 
00617          AST_LIST_INSERT_TAIL(alist, item, entry);
00618       }
00619    }
00620 
00621    return 0;
00622 }

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 350 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().

00351 {
00352    ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, dialcontext);
00353 
00354    if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) {
00355       /* We still want to set the exten though */
00356       ast_copy_string(chan->exten, item->exten, sizeof(chan->exten));
00357    } else if (ast_goto_if_exists(chan, dialcontext, item->exten, 1)) {
00358       ast_log(LOG_WARNING,
00359          "Can't find extension '%s' in context '%s'.  "
00360          "Did you pass the wrong context to Directory?\n",
00361          item->exten, dialcontext);
00362       return -1;
00363    }
00364 
00365    return 0;
00366 }

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 403 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().

00404 {
00405    struct directory_item **block, *item;
00406    int i, limit, res = 0;
00407    char buf[9];
00408 
00409    for (block = items; count; block += limit, count -= limit) {
00410       limit = count;
00411       if (limit > 8)
00412          limit = 8;
00413 
00414       for (i = 0; i < limit && !res; i++) {
00415          item = block[i];
00416 
00417          snprintf(buf, sizeof(buf), "digits/%d", i + 1);
00418          /* Press <num> for <name>, [ extension <ext> ] */
00419          res = ast_streamfile(chan, "dir-multi1", chan->language);
00420          if (!res)
00421             res = ast_waitstream(chan, AST_DIGIT_ANY);
00422          if (!res)
00423             res = ast_streamfile(chan, buf, chan->language);
00424          if (!res)
00425             res = ast_waitstream(chan, AST_DIGIT_ANY);
00426          if (!res)
00427             res = ast_streamfile(chan, "dir-multi2", chan->language);
00428          if (!res)
00429             res = ast_waitstream(chan, AST_DIGIT_ANY);
00430          if (!res)
00431             res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
00432          if (!res)
00433             res = ast_waitstream(chan, AST_DIGIT_ANY);
00434          if (!res)
00435             res = ast_waitfordigit(chan, 800);
00436       }
00437 
00438       /* Press "9" for more names. */
00439       if (!res && count > limit) {
00440          res = ast_streamfile(chan, "dir-multi9", chan->language);
00441          if (!res)
00442             res = ast_waitstream(chan, AST_DIGIT_ANY);
00443       }
00444 
00445       if (!res) {
00446          res = ast_waitfordigit(chan, 3000);
00447       }
00448 
00449       if (res && res > '0' && res < '1' + limit) {
00450          return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1;
00451       }
00452 
00453       if (res < 0)
00454          return -1;
00455 
00456       res = 0;
00457    }
00458 
00459    /* Nothing was selected */
00460    return 0;
00461 }

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 368 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().

00369 {
00370    struct directory_item *item, **ptr;
00371    int i, res, loop;
00372 
00373    for (ptr = items, i = 0; i < count; i++, ptr++) {
00374       item = *ptr;
00375 
00376       for (loop = 3 ; loop > 0; loop--) {
00377          res = play_mailbox_owner(chan, context, item->exten, item->name, flags);
00378 
00379          if (!res)
00380             res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY);
00381          if (!res)
00382             res = ast_waitfordigit(chan, 3000);
00383          ast_stopstream(chan);
00384    
00385          if (res == '1') { /* Name selected */
00386             return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1;
00387          } else if (res == '*') {
00388             /* Skip to next match in list */
00389             break;
00390          }
00391 
00392          if (res < 0)
00393             return -1;
00394 
00395          res = 0;
00396       }
00397    }
00398 
00399    /* Nothing was selected */
00400    return 0;
00401 }

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

Definition at line 624 of file app_directory.c.

References directory_item::key.

Referenced by do_directory().

00625 {
00626    int reordered, i;
00627    struct directory_item **ptr, *tmp;
00628 
00629    if (count < 2)
00630       return;
00631 
00632    /* Bubble-sort items by the key */
00633    do {
00634       reordered = 0;
00635       for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) {
00636          if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) {
00637             tmp = ptr[0];
00638             ptr[0] = ptr[1];
00639             ptr[1] = tmp;
00640             reordered++;
00641          }
00642       }
00643    } while (reordered);
00644 }

static int unload_module ( void   )  [static]

Definition at line 817 of file app_directory.c.

References ast_unregister_application().

00818 {
00819    int res;
00820    res = ast_unregister_application(app);
00821    return res;
00822 }


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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } [static]

Definition at line 849 of file app_directory.c.

char* app = "Directory" [static]

Definition at line 50 of file app_directory.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 849 of file app_directory.c.

char* descrip [static]

Definition at line 53 of file app_directory.c.

struct ast_app_option directory_app_options[128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU },} [static]

Definition at line 104 of file app_directory.c.

Referenced by directory_exec().

enum { ... } directory_option_flags

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

Definition at line 52 of file app_directory.c.


Generated on Thu Jul 9 13:40:44 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7