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