#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, char *opts[]) |
static int | goto_exten (struct ast_channel *chan, const char *dialcontext, char *ext) |
static int | load_module (void) |
static int | play_mailbox_owner (struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags) |
static struct ast_config * | realtime_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, char *opts[]) |
static int | select_item_pause (struct ast_channel *chan, struct ast_flags *flags, char *opts[]) |
static int | select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, const char *context, const char *dialcontext, struct ast_flags *flags, char *opts[]) |
static void | sort_items (struct directory_item **sorted, int count) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_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_info * | ast_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" |
Definition in file app_directory.c.
#define VOICEMAIL_CONFIG "voicemail.conf" |
Definition at line 91 of file app_directory.c.
Referenced by load_config(), realtime_directory(), and vm_change_password().
anonymous enum |
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 |
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 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 807 of file app_directory.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 807 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 437 of file app_directory.c.
References ast_calloc, ast_copy_string(), compare(), and directory_item::key.
Referenced by search_directory().
00438 { 00439 struct directory_item *item; 00440 const char *key = NULL; 00441 int namelen; 00442 00443 00444 /* Set key to last name or first name depending on search mode */ 00445 if (!use_first_name) 00446 key = strchr(item_fullname, ' '); 00447 00448 if (key) 00449 key++; 00450 else 00451 key = item_fullname; 00452 00453 if (compare(key, pattern_ext)) 00454 return 0; 00455 00456 /* Match */ 00457 item = ast_calloc(1, sizeof(*item)); 00458 if (!item) 00459 return -1; 00460 ast_copy_string(item->name, item_fullname, sizeof(item->name)); 00461 ast_copy_string(item->exten, item_ext, sizeof(item->exten)); 00462 00463 ast_copy_string(item->key, key, sizeof(item->key)); 00464 if (key != item_fullname) { 00465 /* Key is the last name. Append first name to key in order to sort Last,First */ 00466 namelen = key - item_fullname - 1; 00467 if (namelen > sizeof(item->key) - strlen(item->key) - 1) 00468 namelen = sizeof(item->key) - strlen(item->key) - 1; 00469 strncat(item->key, item_fullname, namelen); 00470 } 00471 00472 *result = item; 00473 return 1; 00474 }
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 672 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().
00673 { 00674 int res = 0, digit = 3; 00675 struct ast_config *cfg, *ucfg; 00676 const char *dirintro; 00677 char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { "", }; 00678 struct ast_flags flags = { 0 }; 00679 struct ast_flags config_flags = { 0 }; 00680 enum { FIRST, LAST, BOTH } which = LAST; 00681 char digits[9] = "digits/3"; 00682 AST_DECLARE_APP_ARGS(args, 00683 AST_APP_ARG(vmcontext); 00684 AST_APP_ARG(dialcontext); 00685 AST_APP_ARG(options); 00686 ); 00687 00688 if (ast_strlen_zero(data)) { 00689 ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n"); 00690 return -1; 00691 } 00692 00693 parse = ast_strdupa(data); 00694 00695 AST_STANDARD_APP_ARGS(args, parse); 00696 00697 if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options)) 00698 return -1; 00699 00700 if (ast_strlen_zero(args.dialcontext)) 00701 args.dialcontext = args.vmcontext; 00702 00703 cfg = realtime_directory(args.vmcontext); 00704 if (!cfg) { 00705 ast_log(LOG_ERROR, "Unable to read the configuration data!\n"); 00706 return -1; 00707 } 00708 00709 ucfg = ast_config_load("users.conf", config_flags); 00710 00711 dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro"); 00712 if (ast_strlen_zero(dirintro)) 00713 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00714 00715 if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00716 if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) { 00717 digit = atoi(opts[OPT_ARG_EITHER]); 00718 } 00719 which = BOTH; 00720 } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00721 if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) { 00722 digit = atoi(opts[OPT_ARG_FIRSTNAME]); 00723 } 00724 which = FIRST; 00725 } else { 00726 if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) { 00727 digit = atoi(opts[OPT_ARG_LASTNAME]); 00728 } 00729 which = LAST; 00730 } 00731 00732 /* If no options specified, search by last name */ 00733 if (!ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && !ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00734 ast_set_flag(&flags, OPT_LISTBYLASTNAME); 00735 which = LAST; 00736 } 00737 00738 if (digit > 9) { 00739 digit = 9; 00740 } else if (digit < 1) { 00741 digit = 3; 00742 } 00743 digits[7] = digit + '0'; 00744 00745 if (chan->_state != AST_STATE_UP) 00746 res = ast_answer(chan); 00747 00748 for (;;) { 00749 if (!ast_strlen_zero(dirintro) && !res) { 00750 res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY); 00751 } else if (!res) { 00752 /* Stop playing sounds as soon as we have a digit. */ 00753 res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY); 00754 if (!res) { 00755 res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY); 00756 } 00757 if (!res) { 00758 res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY); 00759 } 00760 if (!res) { 00761 res = ast_stream_and_wait(chan, 00762 which == FIRST ? "dir-first" : 00763 which == LAST ? "dir-last" : 00764 "dir-firstlast", AST_DIGIT_ANY); 00765 } 00766 if (!res) { 00767 res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY); 00768 } 00769 } 00770 ast_stopstream(chan); 00771 if (!res) 00772 res = ast_waitfordigit(chan, 5000); 00773 00774 if (res <= 0) 00775 break; 00776 00777 res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags, opts); 00778 if (res) 00779 break; 00780 00781 res = ast_waitstream(chan, AST_DIGIT_ANY); 00782 ast_stopstream(chan); 00783 00784 if (res) 00785 break; 00786 } 00787 00788 if (ucfg) 00789 ast_config_destroy(ucfg); 00790 ast_config_destroy(cfg); 00791 00792 return res < 0 ? -1 : 0; 00793 }
static int do_directory | ( | struct ast_channel * | chan, | |
struct ast_config * | vmcfg, | |||
struct ast_config * | ucfg, | |||
char * | context, | |||
char * | dialcontext, | |||
char | digit, | |||
int | digits, | |||
struct ast_flags * | flags, | |||
char * | opts[] | |||
) | [static] |
Definition at line 588 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().
00589 { 00590 /* Read in the first three digits.. "digit" is the first digit, already read */ 00591 int res = 0; 00592 itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 00593 struct directory_item *item, **ptr, **sorted = NULL; 00594 int count, i; 00595 char ext[10] = ""; 00596 00597 if (ast_strlen_zero(context)) { 00598 ast_log(LOG_WARNING, 00599 "Directory must be called with an argument " 00600 "(context in which to interpret extensions)\n"); 00601 return -1; 00602 } 00603 00604 if (digit == '0' && !goto_exten(chan, dialcontext, "o")) { 00605 return digit; 00606 } 00607 00608 if (digit == '*' && !goto_exten(chan, dialcontext, "a")) { 00609 return digit; 00610 } 00611 00612 ext[0] = digit; 00613 if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0) 00614 return -1; 00615 00616 res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist); 00617 if (res) 00618 goto exit; 00619 00620 /* Count items in the list */ 00621 count = 0; 00622 AST_LIST_TRAVERSE(&alist, item, entry) { 00623 count++; 00624 } 00625 00626 if (count < 1) { 00627 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00628 goto exit; 00629 } 00630 00631 00632 /* Create plain array of pointers to items (for sorting) */ 00633 sorted = ast_calloc(count, sizeof(*sorted)); 00634 00635 ptr = sorted; 00636 AST_LIST_TRAVERSE(&alist, item, entry) { 00637 *ptr++ = item; 00638 } 00639 00640 /* Sort items */ 00641 sort_items(sorted, count); 00642 00643 if (option_debug) { 00644 ast_debug(2, "Listing matching entries:\n"); 00645 for (ptr = sorted, i = 0; i < count; i++, ptr++) { 00646 ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name); 00647 } 00648 } 00649 00650 if (ast_test_flag(flags, OPT_SELECTFROMMENU)) { 00651 /* Offer multiple entries at the same time */ 00652 res = select_item_menu(chan, sorted, count, context, dialcontext, flags, opts); 00653 } else { 00654 /* Offer entries one by one */ 00655 res = select_item_seq(chan, sorted, count, context, dialcontext, flags, opts); 00656 } 00657 00658 if (!res) { 00659 res = ast_streamfile(chan, "dir-nomore", chan->language); 00660 } 00661 00662 exit: 00663 if (sorted) 00664 ast_free(sorted); 00665 00666 while ((item = AST_LIST_REMOVE_HEAD(&alist, entry))) 00667 ast_free(item); 00668 00669 return res; 00670 }
static int goto_exten | ( | struct ast_channel * | chan, | |
const char * | dialcontext, | |||
char * | ext | |||
) | [static] |
Definition at line 575 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().
00576 { 00577 if (!ast_goto_if_exists(chan, dialcontext, ext, 1) || 00578 (!ast_strlen_zero(chan->macrocontext) && 00579 !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) { 00580 return 0; 00581 } else { 00582 ast_log(LOG_WARNING, "Can't find extension '%s' in current context. " 00583 "Not Exiting the Directory!\n", ext); 00584 return -1; 00585 } 00586 }
static int load_module | ( | void | ) | [static] |
Definition at line 802 of file app_directory.c.
References ast_register_application, and directory_exec().
00803 { 00804 return ast_register_application(app, directory_exec, synopsis, descrip); 00805 }
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 374 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().
00375 { 00376 struct ast_config *cfg; 00377 struct ast_config *rtdata; 00378 struct ast_category *cat; 00379 struct ast_variable *var; 00380 char *mailbox; 00381 const char *fullname; 00382 const char *hidefromdir; 00383 char tmp[100]; 00384 struct ast_flags config_flags = { 0 }; 00385 00386 /* Load flat file config. */ 00387 cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); 00388 00389 if (!cfg) { 00390 /* Loading config failed. */ 00391 ast_log(LOG_WARNING, "Loading config failed.\n"); 00392 return NULL; 00393 } 00394 00395 /* Get realtime entries, categorized by their mailbox number 00396 and present in the requested context */ 00397 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL); 00398 00399 /* if there are no results, just return the entries from the config file */ 00400 if (!rtdata) 00401 return cfg; 00402 00403 /* Does the context exist within the config file? If not, make one */ 00404 cat = ast_category_get(cfg, context); 00405 if (!cat) { 00406 cat = ast_category_new(context, "", 99999); 00407 if (!cat) { 00408 ast_log(LOG_WARNING, "Out of memory\n"); 00409 ast_config_destroy(cfg); 00410 if (rtdata) { 00411 ast_config_destroy(rtdata); 00412 } 00413 return NULL; 00414 } 00415 ast_category_append(cfg, cat); 00416 } 00417 00418 mailbox = NULL; 00419 while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { 00420 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00421 if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) { 00422 /* Skip hidden */ 00423 continue; 00424 } 00425 snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, "")); 00426 var = ast_variable_new(mailbox, tmp, ""); 00427 if (var) 00428 ast_variable_append(cat, var); 00429 else 00430 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00431 } 00432 ast_config_destroy(rtdata); 00433 00434 return cfg; 00435 }
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 478 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().
00479 { 00480 struct ast_variable *v; 00481 char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat; 00482 struct directory_item *item; 00483 int res; 00484 00485 ast_debug(2, "Pattern: %s\n", ext); 00486 00487 for (v = ast_variable_browse(vmcfg, context); v; v = v->next) { 00488 00489 /* Ignore hidden */ 00490 if (strcasestr(v->value, "hidefromdir=yes")) 00491 continue; 00492 00493 ast_copy_string(buf, v->value, sizeof(buf)); 00494 bufptr = buf; 00495 00496 /* password,Full Name,email,pager,options */ 00497 strsep(&bufptr, ","); 00498 pos = strsep(&bufptr, ","); 00499 00500 /* No name to compare against */ 00501 if (ast_strlen_zero(pos)) { 00502 continue; 00503 } 00504 00505 res = 0; 00506 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00507 res = check_match(&item, pos, v->name, ext, 0 /* use_first_name */); 00508 } 00509 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00510 res = check_match(&item, pos, v->name, 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 if (ucfg) { 00522 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 00523 const char *position; 00524 if (!strcasecmp(cat, "general")) 00525 continue; 00526 if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) 00527 continue; 00528 00529 /* Find all candidate extensions */ 00530 position = ast_variable_retrieve(ucfg, cat, "fullname"); 00531 if (!position) 00532 continue; 00533 00534 res = 0; 00535 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00536 res = check_match(&item, position, cat, ext, 0 /* use_first_name */); 00537 } 00538 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00539 res = check_match(&item, position, cat, ext, 1 /* use_first_name */); 00540 } 00541 00542 if (!res) 00543 continue; 00544 else if (res < 0) 00545 return -1; 00546 00547 AST_LIST_INSERT_TAIL(alist, item, entry); 00548 } 00549 } 00550 return 0; 00551 }
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, | |||
char * | opts[] | |||
) | [static] |
Definition at line 311 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(), select_entry(), and select_item_pause().
Referenced by do_directory().
00312 { 00313 struct directory_item **block, *item; 00314 int i, limit, res = 0; 00315 char buf[9]; 00316 00317 /* option p(n): cellphone pause option */ 00318 select_item_pause(chan, flags, opts); 00319 00320 for (block = items; count; block += limit, count -= limit) { 00321 limit = count; 00322 if (limit > 8) 00323 limit = 8; 00324 00325 for (i = 0; i < limit && !res; i++) { 00326 item = block[i]; 00327 00328 snprintf(buf, sizeof(buf), "digits/%d", i + 1); 00329 /* Press <num> for <name>, [ extension <ext> ] */ 00330 res = ast_streamfile(chan, "dir-multi1", chan->language); 00331 if (!res) 00332 res = ast_waitstream(chan, AST_DIGIT_ANY); 00333 if (!res) 00334 res = ast_streamfile(chan, buf, chan->language); 00335 if (!res) 00336 res = ast_waitstream(chan, AST_DIGIT_ANY); 00337 if (!res) 00338 res = ast_streamfile(chan, "dir-multi2", chan->language); 00339 if (!res) 00340 res = ast_waitstream(chan, AST_DIGIT_ANY); 00341 if (!res) 00342 res = play_mailbox_owner(chan, context, item->exten, item->name, flags); 00343 if (!res) 00344 res = ast_waitstream(chan, AST_DIGIT_ANY); 00345 if (!res) 00346 res = ast_waitfordigit(chan, 800); 00347 } 00348 00349 /* Press "9" for more names. */ 00350 if (!res && count > limit) { 00351 res = ast_streamfile(chan, "dir-multi9", chan->language); 00352 if (!res) 00353 res = ast_waitstream(chan, AST_DIGIT_ANY); 00354 } 00355 00356 if (!res) { 00357 res = ast_waitfordigit(chan, 3000); 00358 } 00359 00360 if (res && res > '0' && res < '1' + limit) { 00361 return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1; 00362 } 00363 00364 if (res < 0) 00365 return -1; 00366 00367 res = 0; 00368 } 00369 00370 /* Nothing was selected */ 00371 return 0; 00372 }
static int select_item_pause | ( | struct ast_channel * | chan, | |
struct ast_flags * | flags, | |||
char * | opts[] | |||
) | [static] |
Definition at line 255 of file app_directory.c.
References ast_strlen_zero(), ast_test_flag, ast_waitfordigit(), chan, OPT_ARG_PAUSE, and OPT_PAUSE.
Referenced by select_item_menu(), and select_item_seq().
00256 { 00257 int res = 0, opt_pause = 0; 00258 00259 if (ast_test_flag(flags, OPT_PAUSE) && !ast_strlen_zero(opts[OPT_ARG_PAUSE])) { 00260 opt_pause = atoi(opts[OPT_ARG_PAUSE]); 00261 if (opt_pause > 3000) { 00262 opt_pause = 3000; 00263 } 00264 res = ast_waitfordigit(chan, opt_pause); 00265 } 00266 return res; 00267 }
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, | |||
char * | opts[] | |||
) | [static] |
Definition at line 269 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(), select_entry(), and select_item_pause().
Referenced by do_directory().
00271 { 00272 struct directory_item *item, **ptr; 00273 int i, res, loop; 00274 00275 /* option p(n): cellphone pause option */ 00276 /* allow early press of selection key */ 00277 res = select_item_pause(chan, flags, opts); 00278 00279 for (ptr = items, i = 0; i < count; i++, ptr++) { 00280 item = *ptr; 00281 00282 for (loop = 3 ; loop > 0; loop--) { 00283 00284 if (!res) 00285 res = play_mailbox_owner(chan, context, item->exten, item->name, flags); 00286 if (!res) 00287 res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY); 00288 if (!res) 00289 res = ast_waitfordigit(chan, 3000); 00290 ast_stopstream(chan); 00291 00292 if (res == '1') { /* Name selected */ 00293 return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1; 00294 } else if (res == '*') { 00295 /* Skip to next match in list */ 00296 break; 00297 } 00298 00299 if (res < 0) 00300 return -1; 00301 00302 res = 0; 00303 } 00304 res = 0; 00305 } 00306 00307 /* Nothing was selected */ 00308 return 0; 00309 }
static void sort_items | ( | struct directory_item ** | sorted, | |
int | count | |||
) | [static] |
Definition at line 553 of file app_directory.c.
References directory_item::key.
Referenced by do_directory().
00554 { 00555 int reordered, i; 00556 struct directory_item **ptr, *tmp; 00557 00558 if (count < 2) 00559 return; 00560 00561 /* Bubble-sort items by the key */ 00562 do { 00563 reordered = 0; 00564 for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) { 00565 if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) { 00566 tmp = ptr[0]; 00567 ptr[0] = ptr[1]; 00568 ptr[1] = tmp; 00569 reordered++; 00570 } 00571 } 00572 } while (reordered); 00573 }
static int unload_module | ( | void | ) | [static] |
Definition at line 795 of file app_directory.c.
References ast_unregister_application().
00796 { 00797 int res; 00798 res = ast_unregister_application(app); 00799 return res; 00800 }
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 807 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 807 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] |
enum { ... } directory_option_flags |
char* synopsis = "Provide directory of voicemail extensions" [static] |
Definition at line 47 of file app_directory.c.