#include "asterisk.h"
#include <ctype.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
Go to the source code of this file.
Data Structures | |
struct | directory_item |
struct | itemlist |
Defines | |
#define | VOICEMAIL_CONFIG "voicemail.conf" |
Enumerations | |
enum | { OPT_LISTBYFIRSTNAME = (1 << 0), OPT_SAYEXTENSION = (1 << 1), OPT_FROMVOICEMAIL = (1 << 2), OPT_SELECTFROMMENU = (1 << 3), OPT_LISTBYLASTNAME = (1 << 4), OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME, OPT_PAUSE = (1 << 5) } |
enum | { OPT_ARG_FIRSTNAME = 0, OPT_ARG_LASTNAME = 1, OPT_ARG_EITHER = 2, OPT_ARG_PAUSE = 3, OPT_ARG_ARRAY_SIZE = 4 } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | check_match (struct directory_item **result, const char *item_fullname, const char *item_ext, const char *pattern_ext, int use_first_name) |
static int | compare (const char *text, const char *template) |
static int | directory_exec (struct ast_channel *chan, void *data) |
static int | do_directory (struct ast_channel *chan, struct ast_config *vmcfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int digits, struct ast_flags *flags) |
static int | goto_exten (struct ast_channel *chan, const char *dialcontext, char *ext) |
static int | load_module (void) |
static int | play_mailbox_owner (struct ast_channel *chan, const char *context, const char *ext, const char *name, struct ast_flags *flags) |
static struct ast_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) |
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_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 778 of file app_directory.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 778 of file app_directory.c.
static int check_match | ( | struct directory_item ** | result, | |
const char * | item_fullname, | |||
const char * | item_ext, | |||
const char * | pattern_ext, | |||
int | use_first_name | |||
) | [static] |
Definition at line 413 of file app_directory.c.
References ast_calloc, ast_copy_string(), compare(), and directory_item::key.
Referenced by search_directory().
00414 { 00415 struct directory_item *item; 00416 const char *key = NULL; 00417 int namelen; 00418 00419 00420 /* Set key to last name or first name depending on search mode */ 00421 if (!use_first_name) 00422 key = strchr(item_fullname, ' '); 00423 00424 if (key) 00425 key++; 00426 else 00427 key = item_fullname; 00428 00429 if (compare(key, pattern_ext)) 00430 return 0; 00431 00432 /* Match */ 00433 item = ast_calloc(1, sizeof(*item)); 00434 if (!item) 00435 return -1; 00436 ast_copy_string(item->name, item_fullname, sizeof(item->name)); 00437 ast_copy_string(item->exten, item_ext, sizeof(item->exten)); 00438 00439 ast_copy_string(item->key, key, sizeof(item->key)); 00440 if (key != item_fullname) { 00441 /* Key is the last name. Append first name to key in order to sort Last,First */ 00442 namelen = key - item_fullname - 1; 00443 if (namelen > sizeof(item->key) - strlen(item->key) - 1) 00444 namelen = sizeof(item->key) - strlen(item->key) - 1; 00445 strncat(item->key, item_fullname, namelen); 00446 } 00447 00448 *result = item; 00449 return 1; 00450 }
static int compare | ( | const char * | text, | |
const char * | template | |||
) | [static] |
Definition at line 130 of file app_directory.c.
References ast_strlen_zero().
Referenced by ast_hashtab_create(), and check_match().
00131 { 00132 char digit; 00133 00134 if (ast_strlen_zero(text)) { 00135 return -1; 00136 } 00137 00138 while (*template) { 00139 digit = toupper(*text++); 00140 switch (digit) { 00141 case 0: 00142 return -1; 00143 case '1': 00144 digit = '1'; 00145 break; 00146 case '2': 00147 case 'A': 00148 case 'B': 00149 case 'C': 00150 digit = '2'; 00151 break; 00152 case '3': 00153 case 'D': 00154 case 'E': 00155 case 'F': 00156 digit = '3'; 00157 break; 00158 case '4': 00159 case 'G': 00160 case 'H': 00161 case 'I': 00162 digit = '4'; 00163 break; 00164 case '5': 00165 case 'J': 00166 case 'K': 00167 case 'L': 00168 digit = '5'; 00169 break; 00170 case '6': 00171 case 'M': 00172 case 'N': 00173 case 'O': 00174 digit = '6'; 00175 break; 00176 case '7': 00177 case 'P': 00178 case 'Q': 00179 case 'R': 00180 case 'S': 00181 digit = '7'; 00182 break; 00183 case '8': 00184 case 'T': 00185 case 'U': 00186 case 'V': 00187 digit = '8'; 00188 break; 00189 case '9': 00190 case 'W': 00191 case 'X': 00192 case 'Y': 00193 case 'Z': 00194 digit = '9'; 00195 break; 00196 00197 default: 00198 if (digit > ' ') 00199 return -1; 00200 continue; 00201 } 00202 00203 if (*template++ != digit) 00204 return -1; 00205 } 00206 00207 return 0; 00208 }
static int directory_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 643 of file app_directory.c.
References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_config_destroy(), ast_config_load, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, ast_log(), ast_set_flag, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), chan, config_flags, dialcontext, directory_app_options, do_directory(), ast_flags::flags, LOG_ERROR, LOG_WARNING, OPT_ARG_ARRAY_SIZE, OPT_ARG_EITHER, OPT_ARG_FIRSTNAME, OPT_ARG_LASTNAME, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, parse(), and realtime_directory().
Referenced by load_module().
00644 { 00645 int res = 0, digit = 3; 00646 struct ast_config *cfg, *ucfg; 00647 const char *dirintro; 00648 char *parse, *opts[OPT_ARG_ARRAY_SIZE]; 00649 struct ast_flags flags = { 0 }; 00650 struct ast_flags config_flags = { 0 }; 00651 enum { FIRST, LAST, BOTH } which = LAST; 00652 char digits[9] = "digits/3"; 00653 AST_DECLARE_APP_ARGS(args, 00654 AST_APP_ARG(vmcontext); 00655 AST_APP_ARG(dialcontext); 00656 AST_APP_ARG(options); 00657 ); 00658 00659 if (ast_strlen_zero(data)) { 00660 ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n"); 00661 return -1; 00662 } 00663 00664 parse = ast_strdupa(data); 00665 00666 AST_STANDARD_APP_ARGS(args, parse); 00667 00668 if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options)) 00669 return -1; 00670 00671 if (ast_strlen_zero(args.dialcontext)) 00672 args.dialcontext = args.vmcontext; 00673 00674 cfg = realtime_directory(args.vmcontext); 00675 if (!cfg) { 00676 ast_log(LOG_ERROR, "Unable to read the configuration data!\n"); 00677 return -1; 00678 } 00679 00680 ucfg = ast_config_load("users.conf", config_flags); 00681 00682 dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro"); 00683 if (ast_strlen_zero(dirintro)) 00684 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00685 00686 if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00687 if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) { 00688 digit = atoi(opts[OPT_ARG_EITHER]); 00689 } 00690 which = BOTH; 00691 } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00692 if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) { 00693 digit = atoi(opts[OPT_ARG_FIRSTNAME]); 00694 } 00695 which = FIRST; 00696 } else { 00697 if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) { 00698 digit = atoi(opts[OPT_ARG_LASTNAME]); 00699 } 00700 which = LAST; 00701 } 00702 00703 /* If no options specified, search by last name */ 00704 if (!ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && !ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00705 ast_set_flag(&flags, OPT_LISTBYLASTNAME); 00706 which = LAST; 00707 } 00708 00709 if (digit > 9) { 00710 digit = 9; 00711 } else if (digit < 1) { 00712 digit = 3; 00713 } 00714 digits[7] = digit + '0'; 00715 00716 if (chan->_state != AST_STATE_UP) 00717 res = ast_answer(chan); 00718 00719 for (;;) { 00720 if (!ast_strlen_zero(dirintro) && !res) { 00721 res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY); 00722 } else if (!res) { 00723 /* Stop playing sounds as soon as we have a digit. */ 00724 res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY); 00725 if (!res) { 00726 res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY); 00727 } 00728 if (!res) { 00729 res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY); 00730 } 00731 if (!res) { 00732 res = ast_stream_and_wait(chan, 00733 which == FIRST ? "dir-first" : 00734 which == LAST ? "dir-last" : 00735 "dir-firstlast", AST_DIGIT_ANY); 00736 } 00737 if (!res) { 00738 ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY); 00739 } 00740 } 00741 ast_stopstream(chan); 00742 if (!res) 00743 res = ast_waitfordigit(chan, 5000); 00744 00745 if (res <= 0) 00746 break; 00747 00748 res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags); 00749 if (res) 00750 break; 00751 00752 res = ast_waitstream(chan, AST_DIGIT_ANY); 00753 ast_stopstream(chan); 00754 00755 if (res) 00756 break; 00757 } 00758 00759 if (ucfg) 00760 ast_config_destroy(ucfg); 00761 ast_config_destroy(cfg); 00762 00763 return res < 0 ? -1 : 0; 00764 }
static int do_directory | ( | struct ast_channel * | chan, | |
struct ast_config * | vmcfg, | |||
struct ast_config * | ucfg, | |||
char * | context, | |||
char * | dialcontext, | |||
char | digit, | |||
int | digits, | |||
struct ast_flags * | flags | |||
) | [static] |
Definition at line 559 of file app_directory.c.
References ast_calloc, ast_debug, ast_free, AST_LIST_HEAD_NOLOCK_INIT_VALUE, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, ast_log(), ast_readstring(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, chan, directory_item::entry, ext, directory_item::exten, goto_exten(), ast_channel::language, LOG_DEBUG, LOG_WARNING, directory_item::name, OPT_SELECTFROMMENU, option_debug, search_directory(), select_item_menu(), select_item_seq(), and sort_items().
Referenced by directory_exec().
00560 { 00561 /* Read in the first three digits.. "digit" is the first digit, already read */ 00562 int res = 0; 00563 itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 00564 struct directory_item *item, **ptr, **sorted = NULL; 00565 int count, i; 00566 char ext[10] = ""; 00567 00568 if (ast_strlen_zero(context)) { 00569 ast_log(LOG_WARNING, 00570 "Directory must be called with an argument " 00571 "(context in which to interpret extensions)\n"); 00572 return -1; 00573 } 00574 00575 if (digit == '0' && !goto_exten(chan, dialcontext, "o")) { 00576 return 0; 00577 } 00578 00579 if (digit == '*' && !goto_exten(chan, dialcontext, "a")) { 00580 return 0; 00581 } 00582 00583 ext[0] = digit; 00584 if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0) 00585 return -1; 00586 00587 res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist); 00588 if (res) 00589 goto exit; 00590 00591 /* Count items in the list */ 00592 count = 0; 00593 AST_LIST_TRAVERSE(&alist, item, entry) { 00594 count++; 00595 } 00596 00597 if (count < 1) { 00598 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00599 goto exit; 00600 } 00601 00602 00603 /* Create plain array of pointers to items (for sorting) */ 00604 sorted = ast_calloc(count, sizeof(*sorted)); 00605 00606 ptr = sorted; 00607 AST_LIST_TRAVERSE(&alist, item, entry) { 00608 *ptr++ = item; 00609 } 00610 00611 /* Sort items */ 00612 sort_items(sorted, count); 00613 00614 if (option_debug) { 00615 ast_debug(2, "Listing matching entries:\n"); 00616 for (ptr = sorted, i = 0; i < count; i++, ptr++) { 00617 ast_log(LOG_DEBUG, "%s: %s\n", ptr[0]->exten, ptr[0]->name); 00618 } 00619 } 00620 00621 if (ast_test_flag(flags, OPT_SELECTFROMMENU)) { 00622 /* Offer multiple entries at the same time */ 00623 res = select_item_menu(chan, sorted, count, context, dialcontext, flags); 00624 } else { 00625 /* Offer entries one by one */ 00626 res = select_item_seq(chan, sorted, count, context, dialcontext, flags); 00627 } 00628 00629 if (!res) { 00630 res = ast_streamfile(chan, "dir-nomore", chan->language); 00631 } 00632 00633 exit: 00634 if (sorted) 00635 ast_free(sorted); 00636 00637 while ((item = AST_LIST_REMOVE_HEAD(&alist, entry))) 00638 ast_free(item); 00639 00640 return res; 00641 }
static int goto_exten | ( | struct ast_channel * | chan, | |
const char * | dialcontext, | |||
char * | ext | |||
) | [static] |
Definition at line 546 of file app_directory.c.
References ast_goto_if_exists(), ast_log(), ast_strlen_zero(), chan, LOG_WARNING, and ast_channel::macrocontext.
Referenced by do_directory().
00547 { 00548 if (!ast_goto_if_exists(chan, dialcontext, ext, 1) || 00549 (!ast_strlen_zero(chan->macrocontext) && 00550 !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) { 00551 return 0; 00552 } else { 00553 ast_log(LOG_WARNING, "Can't find extension '%s' in current context. " 00554 "Not Exiting the Directory!\n", ext); 00555 return -1; 00556 } 00557 }
static int load_module | ( | void | ) | [static] |
Definition at line 773 of file app_directory.c.
References ast_register_application, and directory_exec().
00774 { 00775 return ast_register_application(app, directory_exec, synopsis, descrip); 00776 }
static int play_mailbox_owner | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | ext, | |||
const char * | name, | |||
struct ast_flags * | flags | |||
) | [static] |
Definition at line 215 of file app_directory.c.
References ast_app_sayname(), AST_DIGIT_ANY, ast_say_character_str(), ast_stopstream(), ast_stream_and_wait(), ast_strlen_zero(), ast_test_flag, chan, ast_channel::language, OPT_SAYEXTENSION, and S_OR.
Referenced by select_item_menu(), and select_item_seq().
00217 { 00218 int res = 0; 00219 if ((res = ast_app_sayname(chan, ext, context)) >= 0) { 00220 ast_stopstream(chan); 00221 /* If Option 'e' was specified, also read the extension number with the name */ 00222 if (ast_test_flag(flags, OPT_SAYEXTENSION)) { 00223 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); 00224 res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); 00225 } 00226 } else { 00227 res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language); 00228 if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) { 00229 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); 00230 res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); 00231 } 00232 } 00233 00234 return res; 00235 }
static struct ast_config* realtime_directory | ( | char * | context | ) | [static] |
Definition at line 350 of file app_directory.c.
References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new(), ast_config_destroy(), ast_config_load, ast_load_realtime_multientry(), ast_log(), ast_true(), ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), config_flags, LOG_WARNING, mailbox, S_OR, SENTINEL, var, and VOICEMAIL_CONFIG.
Referenced by directory_exec().
00351 { 00352 struct ast_config *cfg; 00353 struct ast_config *rtdata; 00354 struct ast_category *cat; 00355 struct ast_variable *var; 00356 char *mailbox; 00357 const char *fullname; 00358 const char *hidefromdir; 00359 char tmp[100]; 00360 struct ast_flags config_flags = { 0 }; 00361 00362 /* Load flat file config. */ 00363 cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); 00364 00365 if (!cfg) { 00366 /* Loading config failed. */ 00367 ast_log(LOG_WARNING, "Loading config failed.\n"); 00368 return NULL; 00369 } 00370 00371 /* Get realtime entries, categorized by their mailbox number 00372 and present in the requested context */ 00373 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL); 00374 00375 /* if there are no results, just return the entries from the config file */ 00376 if (!rtdata) 00377 return cfg; 00378 00379 /* Does the context exist within the config file? If not, make one */ 00380 cat = ast_category_get(cfg, context); 00381 if (!cat) { 00382 cat = ast_category_new(context, "", 99999); 00383 if (!cat) { 00384 ast_log(LOG_WARNING, "Out of memory\n"); 00385 ast_config_destroy(cfg); 00386 if (rtdata) { 00387 ast_config_destroy(rtdata); 00388 } 00389 return NULL; 00390 } 00391 ast_category_append(cfg, cat); 00392 } 00393 00394 mailbox = NULL; 00395 while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { 00396 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00397 if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) { 00398 /* Skip hidden */ 00399 continue; 00400 } 00401 snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, "")); 00402 var = ast_variable_new(mailbox, tmp, ""); 00403 if (var) 00404 ast_variable_append(cat, var); 00405 else 00406 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00407 } 00408 ast_config_destroy(rtdata); 00409 00410 return cfg; 00411 }
static int search_directory | ( | const char * | context, | |
struct ast_config * | vmcfg, | |||
struct ast_config * | ucfg, | |||
const char * | ext, | |||
struct ast_flags | flags, | |||
itemlist * | alist | |||
) | [static] |
Definition at line 454 of file app_directory.c.
References ast_category_browse(), ast_config_option(), ast_copy_string(), ast_debug, AST_LIST_INSERT_TAIL, AST_MAX_EXTENSION, ast_test_flag, ast_true(), ast_variable_browse(), ast_variable_retrieve(), buf, check_match(), directory_item::entry, ast_variable::name, ast_variable::next, OPT_LISTBYFIRSTNAME, OPT_LISTBYLASTNAME, strcasestr(), strsep(), and ast_variable::value.
Referenced by do_directory().
00455 { 00456 struct ast_variable *v; 00457 char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat; 00458 struct directory_item *item; 00459 int res; 00460 00461 ast_debug(2, "Pattern: %s\n", ext); 00462 00463 for (v = ast_variable_browse(vmcfg, context); v; v = v->next) { 00464 00465 /* Ignore hidden */ 00466 if (strcasestr(v->value, "hidefromdir=yes")) 00467 continue; 00468 00469 ast_copy_string(buf, v->value, sizeof(buf)); 00470 bufptr = buf; 00471 00472 /* password,Full Name,email,pager,options */ 00473 strsep(&bufptr, ","); 00474 pos = strsep(&bufptr, ","); 00475 00476 res = 0; 00477 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00478 res = check_match(&item, pos, v->name, ext, 0 /* use_first_name */); 00479 } 00480 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00481 res = check_match(&item, pos, v->name, ext, 1 /* use_first_name */); 00482 } 00483 00484 if (!res) 00485 continue; 00486 else if (res < 0) 00487 return -1; 00488 00489 AST_LIST_INSERT_TAIL(alist, item, entry); 00490 } 00491 00492 if (ucfg) { 00493 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 00494 const char *position; 00495 if (!strcasecmp(cat, "general")) 00496 continue; 00497 if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) 00498 continue; 00499 00500 /* Find all candidate extensions */ 00501 position = ast_variable_retrieve(ucfg, cat, "fullname"); 00502 if (!position) 00503 continue; 00504 00505 res = 0; 00506 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00507 res = check_match(&item, position, cat, ext, 0 /* use_first_name */); 00508 } 00509 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00510 res = check_match(&item, position, cat, ext, 1 /* use_first_name */); 00511 } 00512 00513 if (!res) 00514 continue; 00515 else if (res < 0) 00516 return -1; 00517 00518 AST_LIST_INSERT_TAIL(alist, item, entry); 00519 } 00520 } 00521 return 0; 00522 }
static int select_entry | ( | struct ast_channel * | chan, | |
const char * | context, | |||
const char * | dialcontext, | |||
const struct directory_item * | item, | |||
struct ast_flags * | flags | |||
) | [static] |
Definition at line 237 of file app_directory.c.
References ast_copy_string(), ast_debug, ast_goto_if_exists(), ast_log(), ast_test_flag, chan, ast_channel::exten, directory_item::exten, LOG_WARNING, directory_item::name, and OPT_FROMVOICEMAIL.
Referenced by select_item_menu(), and select_item_seq().
00238 { 00239 ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, dialcontext); 00240 00241 if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) { 00242 /* We still want to set the exten though */ 00243 ast_copy_string(chan->exten, item->exten, sizeof(chan->exten)); 00244 } else if (ast_goto_if_exists(chan, dialcontext, item->exten, 1)) { 00245 ast_log(LOG_WARNING, 00246 "Can't find extension '%s' in context '%s'. " 00247 "Did you pass the wrong context to Directory?\n", 00248 item->exten, dialcontext); 00249 return -1; 00250 } 00251 00252 return 0; 00253 }
static int select_item_menu | ( | struct ast_channel * | chan, | |
struct directory_item ** | items, | |||
int | count, | |||
const char * | context, | |||
const char * | dialcontext, | |||
struct ast_flags * | flags | |||
) | [static] |
Definition at line 290 of file app_directory.c.
References AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, chan, directory_item::exten, ast_channel::language, directory_item::name, play_mailbox_owner(), and select_entry().
Referenced by do_directory().
00291 { 00292 struct directory_item **block, *item; 00293 int i, limit, res = 0; 00294 char buf[9]; 00295 00296 for (block = items; count; block += limit, count -= limit) { 00297 limit = count; 00298 if (limit > 8) 00299 limit = 8; 00300 00301 for (i = 0; i < limit && !res; i++) { 00302 item = block[i]; 00303 00304 snprintf(buf, sizeof(buf), "digits/%d", i + 1); 00305 /* Press <num> for <name>, [ extension <ext> ] */ 00306 res = ast_streamfile(chan, "dir-multi1", chan->language); 00307 if (!res) 00308 res = ast_waitstream(chan, AST_DIGIT_ANY); 00309 if (!res) 00310 res = ast_streamfile(chan, buf, chan->language); 00311 if (!res) 00312 res = ast_waitstream(chan, AST_DIGIT_ANY); 00313 if (!res) 00314 res = ast_streamfile(chan, "dir-multi2", chan->language); 00315 if (!res) 00316 res = ast_waitstream(chan, AST_DIGIT_ANY); 00317 if (!res) 00318 res = play_mailbox_owner(chan, context, item->exten, item->name, flags); 00319 if (!res) 00320 res = ast_waitstream(chan, AST_DIGIT_ANY); 00321 if (!res) 00322 res = ast_waitfordigit(chan, 800); 00323 } 00324 00325 /* Press "9" for more names. */ 00326 if (!res && count > limit) { 00327 res = ast_streamfile(chan, "dir-multi9", chan->language); 00328 if (!res) 00329 res = ast_waitstream(chan, AST_DIGIT_ANY); 00330 } 00331 00332 if (!res) { 00333 res = ast_waitfordigit(chan, 3000); 00334 } 00335 00336 if (res && res > '0' && res < '1' + limit) { 00337 return select_entry(chan, context, dialcontext, block[res - '1'], flags) ? -1 : 1; 00338 } 00339 00340 if (res < 0) 00341 return -1; 00342 00343 res = 0; 00344 } 00345 00346 /* Nothing was selected */ 00347 return 0; 00348 }
static int select_item_seq | ( | struct ast_channel * | chan, | |
struct directory_item ** | items, | |||
int | count, | |||
const char * | context, | |||
const char * | dialcontext, | |||
struct ast_flags * | flags | |||
) | [static] |
Definition at line 255 of file app_directory.c.
References AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_waitfordigit(), chan, directory_item::exten, directory_item::name, play_mailbox_owner(), and select_entry().
Referenced by do_directory().
00256 { 00257 struct directory_item *item, **ptr; 00258 int i, res, loop; 00259 00260 for (ptr = items, i = 0; i < count; i++, ptr++) { 00261 item = *ptr; 00262 00263 for (loop = 3 ; loop > 0; loop--) { 00264 res = play_mailbox_owner(chan, context, item->exten, item->name, flags); 00265 00266 if (!res) 00267 res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY); 00268 if (!res) 00269 res = ast_waitfordigit(chan, 3000); 00270 ast_stopstream(chan); 00271 00272 if (res == '1') { /* Name selected */ 00273 return select_entry(chan, context, dialcontext, item, flags) ? -1 : 1; 00274 } else if (res == '*') { 00275 /* Skip to next match in list */ 00276 break; 00277 } 00278 00279 if (res < 0) 00280 return -1; 00281 00282 res = 0; 00283 } 00284 } 00285 00286 /* Nothing was selected */ 00287 return 0; 00288 }
static void sort_items | ( | struct directory_item ** | sorted, | |
int | count | |||
) | [static] |
Definition at line 524 of file app_directory.c.
References directory_item::key.
Referenced by do_directory().
00525 { 00526 int reordered, i; 00527 struct directory_item **ptr, *tmp; 00528 00529 if (count < 2) 00530 return; 00531 00532 /* Bubble-sort items by the key */ 00533 do { 00534 reordered = 0; 00535 for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) { 00536 if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) { 00537 tmp = ptr[0]; 00538 ptr[0] = ptr[1]; 00539 ptr[1] = tmp; 00540 reordered++; 00541 } 00542 } 00543 } while (reordered); 00544 }
static int unload_module | ( | void | ) | [static] |
Definition at line 766 of file app_directory.c.
References ast_unregister_application().
00767 { 00768 int res; 00769 res = ast_unregister_application(app); 00770 return res; 00771 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Extension Directory" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 778 of file app_directory.c.
char* app = "Directory" [static] |
Definition at line 45 of file app_directory.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 778 of file app_directory.c.
char* descrip [static] |
Definition at line 48 of file app_directory.c.
struct ast_app_option directory_app_options[128] = { [ 'f' ] = { .flag = OPT_LISTBYFIRSTNAME , .arg_index = OPT_ARG_FIRSTNAME + 1 }, [ 'l' ] = { .flag = OPT_LISTBYLASTNAME , .arg_index = OPT_ARG_LASTNAME + 1 }, [ 'b' ] = { .flag = OPT_LISTBYEITHER , .arg_index = OPT_ARG_EITHER + 1 }, [ 'p' ] = { .flag = OPT_PAUSE , .arg_index = OPT_ARG_PAUSE + 1 }, [ 'e' ] = { .flag = OPT_SAYEXTENSION }, [ 'v' ] = { .flag = OPT_FROMVOICEMAIL }, [ 'm' ] = { .flag = OPT_SELECTFROMMENU },} [static] |
enum { ... } directory_option_flags |
char* synopsis = "Provide directory of voicemail extensions" [static] |
Definition at line 47 of file app_directory.c.