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_context, 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 | search_directory_sub (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 *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 *dialcontext, struct ast_flags *flags) |
| static int | select_item_seq (struct ast_channel *chan, struct directory_item **items, int count, 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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } |
| static char * | app = "Directory" |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| 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 |
Provide a directory of extensions.
Definition in file app_directory.c.
| #define VOICEMAIL_CONFIG "voicemail.conf" |
Definition at line 122 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 124 of file app_directory.c.
00124 { 00125 OPT_LISTBYFIRSTNAME = (1 << 0), 00126 OPT_SAYEXTENSION = (1 << 1), 00127 OPT_FROMVOICEMAIL = (1 << 2), 00128 OPT_SELECTFROMMENU = (1 << 3), 00129 OPT_LISTBYLASTNAME = (1 << 4), 00130 OPT_LISTBYEITHER = OPT_LISTBYFIRSTNAME | OPT_LISTBYLASTNAME, 00131 OPT_PAUSE = (1 << 5), 00132 } directory_option_flags;
| anonymous enum |
Definition at line 134 of file app_directory.c.
00134 { 00135 OPT_ARG_FIRSTNAME = 0, 00136 OPT_ARG_LASTNAME = 1, 00137 OPT_ARG_EITHER = 2, 00138 OPT_ARG_PAUSE = 3, 00139 /* This *must* be the last value in this enum! */ 00140 OPT_ARG_ARRAY_SIZE = 4, 00141 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 852 of file app_directory.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 852 of file app_directory.c.
| static int check_match | ( | struct directory_item ** | result, | |
| const char * | item_context, | |||
| const char * | item_fullname, | |||
| const char * | item_ext, | |||
| const char * | pattern_ext, | |||
| int | use_first_name | |||
| ) | [static] |
Definition at line 460 of file app_directory.c.
References ast_calloc, ast_copy_string(), ast_debug, ast_strlen_zero(), compare(), directory_item::context, directory_item::exten, directory_item::key, and directory_item::name.
Referenced by search_directory_sub().
00461 { 00462 struct directory_item *item; 00463 const char *key = NULL; 00464 int namelen; 00465 00466 if (ast_strlen_zero(item_fullname)) { 00467 return 0; 00468 } 00469 00470 /* Set key to last name or first name depending on search mode */ 00471 if (!use_first_name) 00472 key = strchr(item_fullname, ' '); 00473 00474 if (key) 00475 key++; 00476 else 00477 key = item_fullname; 00478 00479 if (compare(key, pattern_ext)) 00480 return 0; 00481 00482 ast_debug(1, "Found match %s@%s\n", item_ext, item_context); 00483 00484 /* Match */ 00485 item = ast_calloc(1, sizeof(*item)); 00486 if (!item) 00487 return -1; 00488 ast_copy_string(item->context, item_context, sizeof(item->context)); 00489 ast_copy_string(item->name, item_fullname, sizeof(item->name)); 00490 ast_copy_string(item->exten, item_ext, sizeof(item->exten)); 00491 00492 ast_copy_string(item->key, key, sizeof(item->key)); 00493 if (key != item_fullname) { 00494 /* Key is the last name. Append first name to key in order to sort Last,First */ 00495 namelen = key - item_fullname - 1; 00496 if (namelen > sizeof(item->key) - strlen(item->key) - 1) 00497 namelen = sizeof(item->key) - strlen(item->key) - 1; 00498 strncat(item->key, item_fullname, namelen); 00499 } 00500 00501 *result = item; 00502 return 1; 00503 }
| static int compare | ( | const char * | text, | |
| const char * | template | |||
| ) | [static] |
Definition at line 162 of file app_directory.c.
References ast_strlen_zero().
Referenced by ast_hashtab_create(), and check_match().
00163 { 00164 char digit; 00165 00166 if (ast_strlen_zero(text)) { 00167 return -1; 00168 } 00169 00170 while (*template) { 00171 digit = toupper(*text++); 00172 switch (digit) { 00173 case 0: 00174 return -1; 00175 case '1': 00176 digit = '1'; 00177 break; 00178 case '2': 00179 case 'A': 00180 case 'B': 00181 case 'C': 00182 digit = '2'; 00183 break; 00184 case '3': 00185 case 'D': 00186 case 'E': 00187 case 'F': 00188 digit = '3'; 00189 break; 00190 case '4': 00191 case 'G': 00192 case 'H': 00193 case 'I': 00194 digit = '4'; 00195 break; 00196 case '5': 00197 case 'J': 00198 case 'K': 00199 case 'L': 00200 digit = '5'; 00201 break; 00202 case '6': 00203 case 'M': 00204 case 'N': 00205 case 'O': 00206 digit = '6'; 00207 break; 00208 case '7': 00209 case 'P': 00210 case 'Q': 00211 case 'R': 00212 case 'S': 00213 digit = '7'; 00214 break; 00215 case '8': 00216 case 'T': 00217 case 'U': 00218 case 'V': 00219 digit = '8'; 00220 break; 00221 case '9': 00222 case 'W': 00223 case 'X': 00224 case 'Y': 00225 case 'Z': 00226 digit = '9'; 00227 break; 00228 00229 default: 00230 if (digit > ' ') 00231 return -1; 00232 continue; 00233 } 00234 00235 if (*template++ != digit) 00236 return -1; 00237 } 00238 00239 return 0; 00240 }
| static int directory_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Definition at line 723 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_stream_and_wait(), ast_strlen_zero(), ast_test_flag, ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), CONFIG_STATUS_FILEINVALID, dialcontext, directory_app_options, do_directory(), LOG_ERROR, 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().
00724 { 00725 int res = 0, digit = 3; 00726 struct ast_config *cfg, *ucfg; 00727 const char *dirintro; 00728 char *parse, *opts[OPT_ARG_ARRAY_SIZE] = { 0, }; 00729 struct ast_flags flags = { 0 }; 00730 struct ast_flags config_flags = { 0 }; 00731 enum { FIRST, LAST, BOTH } which = LAST; 00732 char digits[9] = "digits/3"; 00733 AST_DECLARE_APP_ARGS(args, 00734 AST_APP_ARG(vmcontext); 00735 AST_APP_ARG(dialcontext); 00736 AST_APP_ARG(options); 00737 ); 00738 00739 parse = ast_strdupa(data); 00740 00741 AST_STANDARD_APP_ARGS(args, parse); 00742 00743 if (args.options && ast_app_parse_options(directory_app_options, &flags, opts, args.options)) 00744 return -1; 00745 00746 if (!(cfg = realtime_directory(args.vmcontext))) { 00747 ast_log(LOG_ERROR, "Unable to read the configuration data!\n"); 00748 return -1; 00749 } 00750 00751 if ((ucfg = ast_config_load("users.conf", config_flags)) == CONFIG_STATUS_FILEINVALID) { 00752 ast_log(LOG_ERROR, "Config file users.conf is in an invalid format. Aborting.\n"); 00753 ucfg = NULL; 00754 } 00755 00756 dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro"); 00757 if (ast_strlen_zero(dirintro)) 00758 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00759 00760 if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00761 if (!ast_strlen_zero(opts[OPT_ARG_EITHER])) { 00762 digit = atoi(opts[OPT_ARG_EITHER]); 00763 } 00764 which = BOTH; 00765 } else if (ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00766 if (!ast_strlen_zero(opts[OPT_ARG_FIRSTNAME])) { 00767 digit = atoi(opts[OPT_ARG_FIRSTNAME]); 00768 } 00769 which = FIRST; 00770 } else { 00771 if (!ast_strlen_zero(opts[OPT_ARG_LASTNAME])) { 00772 digit = atoi(opts[OPT_ARG_LASTNAME]); 00773 } 00774 which = LAST; 00775 } 00776 00777 /* If no options specified, search by last name */ 00778 if (!ast_test_flag(&flags, OPT_LISTBYFIRSTNAME) && !ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00779 ast_set_flag(&flags, OPT_LISTBYLASTNAME); 00780 which = LAST; 00781 } 00782 00783 if (digit > 9) { 00784 digit = 9; 00785 } else if (digit < 1) { 00786 digit = 3; 00787 } 00788 digits[7] = digit + '0'; 00789 00790 if (chan->_state != AST_STATE_UP) 00791 res = ast_answer(chan); 00792 00793 for (;;) { 00794 if (!ast_strlen_zero(dirintro) && !res) { 00795 res = ast_stream_and_wait(chan, dirintro, AST_DIGIT_ANY); 00796 } else if (!res) { 00797 /* Stop playing sounds as soon as we have a digit. */ 00798 res = ast_stream_and_wait(chan, "dir-welcome", AST_DIGIT_ANY); 00799 if (!res) { 00800 res = ast_stream_and_wait(chan, "dir-pls-enter", AST_DIGIT_ANY); 00801 } 00802 if (!res) { 00803 res = ast_stream_and_wait(chan, digits, AST_DIGIT_ANY); 00804 } 00805 if (!res) { 00806 res = ast_stream_and_wait(chan, 00807 which == FIRST ? "dir-first" : 00808 which == LAST ? "dir-last" : 00809 "dir-firstlast", AST_DIGIT_ANY); 00810 } 00811 if (!res) { 00812 res = ast_stream_and_wait(chan, "dir-usingkeypad", AST_DIGIT_ANY); 00813 } 00814 } 00815 ast_stopstream(chan); 00816 if (!res) 00817 res = ast_waitfordigit(chan, 5000); 00818 00819 if (res <= 0) 00820 break; 00821 00822 res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, digit, &flags); 00823 if (res) 00824 break; 00825 00826 res = ast_waitstream(chan, AST_DIGIT_ANY); 00827 ast_stopstream(chan); 00828 00829 if (res) 00830 break; 00831 } 00832 00833 if (ucfg) 00834 ast_config_destroy(ucfg); 00835 ast_config_destroy(cfg); 00836 00837 return res < 0 ? -1 : 0; 00838 }
| 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 646 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_readstring(), ast_streamfile(), ast_test_flag, directory_item::entry, ext, directory_item::exten, goto_exten(), ast_channel::language, directory_item::name, OPT_SELECTFROMMENU, option_debug, S_OR, search_directory(), select_item_menu(), select_item_seq(), and sort_items().
Referenced by directory_exec().
00647 { 00648 /* Read in the first three digits.. "digit" is the first digit, already read */ 00649 int res = 0; 00650 itemlist alist = AST_LIST_HEAD_NOLOCK_INIT_VALUE; 00651 struct directory_item *item, **ptr, **sorted = NULL; 00652 int count, i; 00653 char ext[10] = ""; 00654 00655 if (digit == '0' && !goto_exten(chan, S_OR(dialcontext, "default"), "o")) { 00656 return digit; 00657 } 00658 00659 if (digit == '*' && !goto_exten(chan, S_OR(dialcontext, "default"), "a")) { 00660 return digit; 00661 } 00662 00663 ext[0] = digit; 00664 if (ast_readstring(chan, ext + 1, digits - 1, 3000, 3000, "#") < 0) 00665 return -1; 00666 00667 res = search_directory(context, vmcfg, ucfg, ext, *flags, &alist); 00668 if (res) 00669 goto exit; 00670 00671 /* Count items in the list */ 00672 count = 0; 00673 AST_LIST_TRAVERSE(&alist, item, entry) { 00674 count++; 00675 } 00676 00677 if (count < 1) { 00678 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00679 goto exit; 00680 } 00681 00682 00683 /* Create plain array of pointers to items (for sorting) */ 00684 sorted = ast_calloc(count, sizeof(*sorted)); 00685 00686 ptr = sorted; 00687 AST_LIST_TRAVERSE(&alist, item, entry) { 00688 *ptr++ = item; 00689 } 00690 00691 /* Sort items */ 00692 sort_items(sorted, count); 00693 00694 if (option_debug) { 00695 ast_debug(2, "Listing matching entries:\n"); 00696 for (ptr = sorted, i = 0; i < count; i++, ptr++) { 00697 ast_debug(2, "%s: %s\n", ptr[0]->exten, ptr[0]->name); 00698 } 00699 } 00700 00701 if (ast_test_flag(flags, OPT_SELECTFROMMENU)) { 00702 /* Offer multiple entries at the same time */ 00703 res = select_item_menu(chan, sorted, count, dialcontext, flags); 00704 } else { 00705 /* Offer entries one by one */ 00706 res = select_item_seq(chan, sorted, count, dialcontext, flags); 00707 } 00708 00709 if (!res) { 00710 res = ast_streamfile(chan, "dir-nomore", chan->language); 00711 } 00712 00713 exit: 00714 if (sorted) 00715 ast_free(sorted); 00716 00717 while ((item = AST_LIST_REMOVE_HEAD(&alist, entry))) 00718 ast_free(item); 00719 00720 return res; 00721 }
| static int goto_exten | ( | struct ast_channel * | chan, | |
| const char * | dialcontext, | |||
| char * | ext | |||
| ) | [static] |
Definition at line 633 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().
00634 { 00635 if (!ast_goto_if_exists(chan, dialcontext, ext, 1) || 00636 (!ast_strlen_zero(chan->macrocontext) && 00637 !ast_goto_if_exists(chan, chan->macrocontext, ext, 1))) { 00638 return 0; 00639 } else { 00640 ast_log(LOG_WARNING, "Can't find extension '%s' in current context. " 00641 "Not Exiting the Directory!\n", ext); 00642 return -1; 00643 } 00644 }
| static int load_module | ( | void | ) | [static] |
Definition at line 847 of file app_directory.c.
References ast_register_application_xml, and directory_exec().
00848 { 00849 return ast_register_application_xml(app, directory_exec); 00850 }
| 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 247 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, ast_channel::language, OPT_SAYEXTENSION, and S_OR.
Referenced by select_item_menu(), and select_item_seq().
00249 { 00250 int res = 0; 00251 if ((res = ast_app_sayname(chan, ext, context)) >= 0) { 00252 ast_stopstream(chan); 00253 /* If Option 'e' was specified, also read the extension number with the name */ 00254 if (ast_test_flag(flags, OPT_SAYEXTENSION)) { 00255 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); 00256 res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); 00257 } 00258 } else { 00259 res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language); 00260 if (!ast_strlen_zero(name) && ast_test_flag(flags, OPT_SAYEXTENSION)) { 00261 ast_stream_and_wait(chan, "vm-extension", AST_DIGIT_ANY); 00262 res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language); 00263 } 00264 } 00265 00266 return res; 00267 }
| static struct ast_config* realtime_directory | ( | char * | context | ) | [static, read] |
Definition at line 382 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_strlen_zero(), ast_true(), ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), CONFIG_STATUS_FILEINVALID, LOG_ERROR, LOG_WARNING, mailbox, S_OR, SENTINEL, var, and VOICEMAIL_CONFIG.
Referenced by directory_exec().
00383 { 00384 struct ast_config *cfg; 00385 struct ast_config *rtdata; 00386 struct ast_category *cat; 00387 struct ast_variable *var; 00388 char *mailbox; 00389 const char *fullname; 00390 const char *hidefromdir, *searchcontexts = NULL; 00391 char tmp[100]; 00392 struct ast_flags config_flags = { 0 }; 00393 00394 /* Load flat file config. */ 00395 cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags); 00396 00397 if (!cfg) { 00398 /* Loading config failed. */ 00399 ast_log(LOG_WARNING, "Loading config failed.\n"); 00400 return NULL; 00401 } else if (cfg == CONFIG_STATUS_FILEINVALID) { 00402 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", VOICEMAIL_CONFIG); 00403 return NULL; 00404 } 00405 00406 /* Get realtime entries, categorized by their mailbox number 00407 and present in the requested context */ 00408 if (ast_strlen_zero(context) && (searchcontexts = ast_variable_retrieve(cfg, "general", "searchcontexts"))) { 00409 if (ast_true(searchcontexts)) { 00410 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", SENTINEL); 00411 context = NULL; 00412 } else { 00413 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", "default", SENTINEL); 00414 context = "default"; 00415 } 00416 } else { 00417 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, SENTINEL); 00418 } 00419 00420 /* if there are no results, just return the entries from the config file */ 00421 if (!rtdata) { 00422 return cfg; 00423 } 00424 00425 mailbox = NULL; 00426 while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) { 00427 const char *context = ast_variable_retrieve(rtdata, mailbox, "context"); 00428 00429 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00430 if (ast_true((hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir")))) { 00431 /* Skip hidden */ 00432 continue; 00433 } 00434 snprintf(tmp, sizeof(tmp), "no-password,%s", S_OR(fullname, "")); 00435 00436 /* Does the context exist within the config file? If not, make one */ 00437 if (!(cat = ast_category_get(cfg, context))) { 00438 if (!(cat = ast_category_new(context, "", 99999))) { 00439 ast_log(LOG_WARNING, "Out of memory\n"); 00440 ast_config_destroy(cfg); 00441 if (rtdata) { 00442 ast_config_destroy(rtdata); 00443 } 00444 return NULL; 00445 } 00446 ast_category_append(cfg, cat); 00447 } 00448 00449 if ((var = ast_variable_new(mailbox, tmp, ""))) { 00450 ast_variable_append(cat, var); 00451 } else { 00452 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00453 } 00454 } 00455 ast_config_destroy(rtdata); 00456 00457 return cfg; 00458 }
| 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 582 of file app_directory.c.
References ast_category_browse(), ast_debug, ast_strlen_zero(), ast_true(), ast_variable_retrieve(), and search_directory_sub().
Referenced by do_directory().
00583 { 00584 const char *searchcontexts = ast_variable_retrieve(vmcfg, "general", "searchcontexts"); 00585 if (ast_strlen_zero(context)) { 00586 if (!ast_strlen_zero(searchcontexts) && ast_true(searchcontexts)) { 00587 /* Browse each context for a match */ 00588 int res; 00589 const char *catg; 00590 for (catg = ast_category_browse(vmcfg, NULL); catg; catg = ast_category_browse(vmcfg, catg)) { 00591 if (!strcmp(catg, "general") || !strcmp(catg, "zonemessages")) { 00592 continue; 00593 } 00594 00595 if ((res = search_directory_sub(catg, vmcfg, ucfg, ext, flags, alist))) { 00596 return res; 00597 } 00598 } 00599 return 0; 00600 } else { 00601 ast_debug(1, "Searching by category default\n"); 00602 return search_directory_sub("default", vmcfg, ucfg, ext, flags, alist); 00603 } 00604 } else { 00605 /* Browse only the listed context for a match */ 00606 ast_debug(1, "Searching by category %s\n", context); 00607 return search_directory_sub(context, vmcfg, ucfg, ext, flags, alist); 00608 } 00609 }
| static int search_directory_sub | ( | const char * | context, | |
| struct ast_config * | vmcfg, | |||
| struct ast_config * | ucfg, | |||
| const char * | ext, | |||
| struct ast_flags | flags, | |||
| itemlist * | alist | |||
| ) | [static] |
Definition at line 507 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, and ast_variable::value.
Referenced by search_directory().
00508 { 00509 struct ast_variable *v; 00510 char buf[AST_MAX_EXTENSION + 1], *pos, *bufptr, *cat; 00511 struct directory_item *item; 00512 int res; 00513 00514 ast_debug(2, "Pattern: %s\n", ext); 00515 00516 for (v = ast_variable_browse(vmcfg, context); v; v = v->next) { 00517 00518 /* Ignore hidden */ 00519 if (strcasestr(v->value, "hidefromdir=yes")) 00520 continue; 00521 00522 ast_copy_string(buf, v->value, sizeof(buf)); 00523 bufptr = buf; 00524 00525 /* password,Full Name,email,pager,options */ 00526 strsep(&bufptr, ","); 00527 pos = strsep(&bufptr, ","); 00528 00529 /* No name to compare against */ 00530 if (ast_strlen_zero(pos)) { 00531 continue; 00532 } 00533 00534 res = 0; 00535 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00536 res = check_match(&item, context, pos, v->name, ext, 0 /* use_first_name */); 00537 } 00538 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00539 res = check_match(&item, context, pos, v->name, 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 if (ucfg) { 00551 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) { 00552 const char *position; 00553 if (!strcasecmp(cat, "general")) 00554 continue; 00555 if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory"))) 00556 continue; 00557 00558 /* Find all candidate extensions */ 00559 position = ast_variable_retrieve(ucfg, cat, "fullname"); 00560 if (!position) 00561 continue; 00562 00563 res = 0; 00564 if (ast_test_flag(&flags, OPT_LISTBYLASTNAME)) { 00565 res = check_match(&item, context, position, cat, ext, 0 /* use_first_name */); 00566 } 00567 if (!res && ast_test_flag(&flags, OPT_LISTBYFIRSTNAME)) { 00568 res = check_match(&item, context, position, cat, ext, 1 /* use_first_name */); 00569 } 00570 00571 if (!res) 00572 continue; 00573 else if (res < 0) 00574 return -1; 00575 00576 AST_LIST_INSERT_TAIL(alist, item, entry); 00577 } 00578 } 00579 return 0; 00580 }
| static int select_entry | ( | struct ast_channel * | chan, | |
| const char * | dialcontext, | |||
| const struct directory_item * | item, | |||
| struct ast_flags * | flags | |||
| ) | [static] |
Definition at line 269 of file app_directory.c.
References ast_copy_string(), ast_debug, ast_goto_if_exists(), ast_log(), ast_test_flag, directory_item::context, ast_channel::exten, directory_item::exten, LOG_WARNING, directory_item::name, OPT_FROMVOICEMAIL, and S_OR.
Referenced by select_item_menu(), and select_item_seq().
00270 { 00271 ast_debug(1, "Selecting '%s' - %s@%s\n", item->name, item->exten, S_OR(dialcontext, item->context)); 00272 00273 if (ast_test_flag(flags, OPT_FROMVOICEMAIL)) { 00274 /* We still want to set the exten though */ 00275 ast_copy_string(chan->exten, item->exten, sizeof(chan->exten)); 00276 } else if (ast_goto_if_exists(chan, S_OR(dialcontext, item->context), item->exten, 1)) { 00277 ast_log(LOG_WARNING, 00278 "Can't find extension '%s' in context '%s'. " 00279 "Did you pass the wrong context to Directory?\n", 00280 item->exten, S_OR(dialcontext, item->context)); 00281 return -1; 00282 } 00283 00284 return 0; 00285 }
| static int select_item_menu | ( | struct ast_channel * | chan, | |
| struct directory_item ** | items, | |||
| int | count, | |||
| const char * | dialcontext, | |||
| struct ast_flags * | flags | |||
| ) | [static] |
Definition at line 322 of file app_directory.c.
References AST_DIGIT_ANY, ast_streamfile(), ast_waitfordigit(), ast_waitstream(), buf, directory_item::context, directory_item::exten, ast_channel::language, directory_item::name, play_mailbox_owner(), and select_entry().
Referenced by do_directory().
00323 { 00324 struct directory_item **block, *item; 00325 int i, limit, res = 0; 00326 char buf[9]; 00327 00328 for (block = items; count; block += limit, count -= limit) { 00329 limit = count; 00330 if (limit > 8) 00331 limit = 8; 00332 00333 for (i = 0; i < limit && !res; i++) { 00334 item = block[i]; 00335 00336 snprintf(buf, sizeof(buf), "digits/%d", i + 1); 00337 /* Press <num> for <name>, [ extension <ext> ] */ 00338 res = ast_streamfile(chan, "dir-multi1", chan->language); 00339 if (!res) 00340 res = ast_waitstream(chan, AST_DIGIT_ANY); 00341 if (!res) 00342 res = ast_streamfile(chan, buf, chan->language); 00343 if (!res) 00344 res = ast_waitstream(chan, AST_DIGIT_ANY); 00345 if (!res) 00346 res = ast_streamfile(chan, "dir-multi2", chan->language); 00347 if (!res) 00348 res = ast_waitstream(chan, AST_DIGIT_ANY); 00349 if (!res) 00350 res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags); 00351 if (!res) 00352 res = ast_waitstream(chan, AST_DIGIT_ANY); 00353 if (!res) 00354 res = ast_waitfordigit(chan, 800); 00355 } 00356 00357 /* Press "9" for more names. */ 00358 if (!res && count > limit) { 00359 res = ast_streamfile(chan, "dir-multi9", chan->language); 00360 if (!res) 00361 res = ast_waitstream(chan, AST_DIGIT_ANY); 00362 } 00363 00364 if (!res) { 00365 res = ast_waitfordigit(chan, 3000); 00366 } 00367 00368 if (res && res > '0' && res < '1' + limit) { 00369 return select_entry(chan, dialcontext, block[res - '1'], flags) ? -1 : 1; 00370 } 00371 00372 if (res < 0) 00373 return -1; 00374 00375 res = 0; 00376 } 00377 00378 /* Nothing was selected */ 00379 return 0; 00380 }
| static int select_item_seq | ( | struct ast_channel * | chan, | |
| struct directory_item ** | items, | |||
| int | count, | |||
| const char * | dialcontext, | |||
| struct ast_flags * | flags | |||
| ) | [static] |
Definition at line 287 of file app_directory.c.
References AST_DIGIT_ANY, ast_stopstream(), ast_stream_and_wait(), ast_waitfordigit(), directory_item::context, directory_item::exten, directory_item::name, play_mailbox_owner(), and select_entry().
Referenced by do_directory().
00288 { 00289 struct directory_item *item, **ptr; 00290 int i, res, loop; 00291 00292 for (ptr = items, i = 0; i < count; i++, ptr++) { 00293 item = *ptr; 00294 00295 for (loop = 3 ; loop > 0; loop--) { 00296 res = play_mailbox_owner(chan, item->context, item->exten, item->name, flags); 00297 00298 if (!res) 00299 res = ast_stream_and_wait(chan, "dir-instr", AST_DIGIT_ANY); 00300 if (!res) 00301 res = ast_waitfordigit(chan, 3000); 00302 ast_stopstream(chan); 00303 00304 if (res == '1') { /* Name selected */ 00305 return select_entry(chan, dialcontext, item, flags) ? -1 : 1; 00306 } else if (res == '*') { 00307 /* Skip to next match in list */ 00308 break; 00309 } 00310 00311 if (res < 0) 00312 return -1; 00313 00314 res = 0; 00315 } 00316 } 00317 00318 /* Nothing was selected */ 00319 return 0; 00320 }
| static void sort_items | ( | struct directory_item ** | sorted, | |
| int | count | |||
| ) | [static] |
Definition at line 611 of file app_directory.c.
References directory_item::key.
Referenced by do_directory().
00612 { 00613 int reordered, i; 00614 struct directory_item **ptr, *tmp; 00615 00616 if (count < 2) 00617 return; 00618 00619 /* Bubble-sort items by the key */ 00620 do { 00621 reordered = 0; 00622 for (ptr = sorted, i = 0; i < count - 1; i++, ptr++) { 00623 if (strcasecmp(ptr[0]->key, ptr[1]->key) > 0) { 00624 tmp = ptr[0]; 00625 ptr[0] = ptr[1]; 00626 ptr[1] = tmp; 00627 reordered++; 00628 } 00629 } 00630 } while (reordered); 00631 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 840 of file app_directory.c.
References ast_unregister_application().
00841 { 00842 int res; 00843 res = ast_unregister_application(app); 00844 return res; 00845 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 852 of file app_directory.c.
char* app = "Directory" [static] |
Definition at line 117 of file app_directory.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 852 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 160 of file app_directory.c.
Referenced by directory_exec().
| enum { ... } directory_option_flags |
1.6.2