#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/utils.h"
Include dependency graph for app_directory.c:
Go to the source code of this file.
Defines | |
#define | NUMDIGITS 3 |
#define | VOICEMAIL_CONFIG "voicemail.conf" |
Functions | |
static char * | convert (char *lastname) |
char * | description (void) |
Provides a description of the module. | |
static int | directory_exec (struct ast_channel *chan, void *data) |
static int | do_directory (struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static int | play_mailbox_owner (struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) |
static struct ast_config * | realtime_directory (char *context) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | app = "Directory" |
static char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
static char * | synopsis = "Provide directory of voicemail extensions" |
static char * | tdesc = "Extension Directory" |
Definition in file app_directory.c.
|
Definition at line 84 of file app_directory.c. Referenced by convert(), and do_directory(). |
|
Definition at line 81 of file app_directory.c. Referenced by load_config(), load_module(), and realtime_directory(). |
|
Definition at line 185 of file app_directory.c. References malloc, and NUMDIGITS. Referenced by do_directory(). 00186 { 00187 char *tmp; 00188 int lcount = 0; 00189 tmp = malloc(NUMDIGITS + 1); 00190 if (tmp) { 00191 while((*lastname > 32) && lcount < NUMDIGITS) { 00192 switch(toupper(*lastname)) { 00193 case '1': 00194 tmp[lcount++] = '1'; 00195 break; 00196 case '2': 00197 case 'A': 00198 case 'B': 00199 case 'C': 00200 tmp[lcount++] = '2'; 00201 break; 00202 case '3': 00203 case 'D': 00204 case 'E': 00205 case 'F': 00206 tmp[lcount++] = '3'; 00207 break; 00208 case '4': 00209 case 'G': 00210 case 'H': 00211 case 'I': 00212 tmp[lcount++] = '4'; 00213 break; 00214 case '5': 00215 case 'J': 00216 case 'K': 00217 case 'L': 00218 tmp[lcount++] = '5'; 00219 break; 00220 case '6': 00221 case 'M': 00222 case 'N': 00223 case 'O': 00224 tmp[lcount++] = '6'; 00225 break; 00226 case '7': 00227 case 'P': 00228 case 'Q': 00229 case 'R': 00230 case 'S': 00231 tmp[lcount++] = '7'; 00232 break; 00233 case '8': 00234 case 'T': 00235 case 'U': 00236 case 'V': 00237 tmp[lcount++] = '8'; 00238 break; 00239 case '9': 00240 case 'W': 00241 case 'X': 00242 case 'Y': 00243 case 'Z': 00244 tmp[lcount++] = '9'; 00245 break; 00246 } 00247 lastname++; 00248 } 00249 tmp[lcount] = '\0'; 00250 } 00251 return tmp; 00252 }
|
|
Provides a description of the module.
Definition at line 635 of file app_directory.c. References tdesc. 00636 { 00637 return tdesc; 00638 }
|
|
Definition at line 526 of file app_directory.c. References ast_answer(), ast_config_destroy(), AST_DIGIT_ANY, ast_log(), AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), cfg, context, dialcontext, do_directory(), last, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, and realtime_directory(). Referenced by load_module(). 00527 { 00528 int res = 0; 00529 struct localuser *u; 00530 struct ast_config *cfg; 00531 int last = 1; 00532 char *context, *dialcontext, *dirintro, *options; 00533 00534 if (ast_strlen_zero(data)) { 00535 ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n"); 00536 return -1; 00537 } 00538 00539 LOCAL_USER_ADD(u); 00540 00541 context = ast_strdupa(data); 00542 dialcontext = strchr(context, '|'); 00543 if (dialcontext) { 00544 *dialcontext = '\0'; 00545 dialcontext++; 00546 options = strchr(dialcontext, '|'); 00547 if (options) { 00548 *options = '\0'; 00549 options++; 00550 if (strchr(options, 'f')) 00551 last = 0; 00552 } 00553 } else 00554 dialcontext = context; 00555 00556 cfg = realtime_directory(context); 00557 if (!cfg) { 00558 LOCAL_USER_REMOVE(u); 00559 return -1; 00560 } 00561 00562 dirintro = ast_variable_retrieve(cfg, context, "directoryintro"); 00563 if (ast_strlen_zero(dirintro)) 00564 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00565 if (ast_strlen_zero(dirintro)) { 00566 if (last) 00567 dirintro = "dir-intro"; 00568 else 00569 dirintro = "dir-intro-fn"; 00570 } 00571 00572 if (chan->_state != AST_STATE_UP) 00573 res = ast_answer(chan); 00574 00575 for (;;) { 00576 if (!res) 00577 res = ast_streamfile(chan, dirintro, chan->language); 00578 if (!res) 00579 res = ast_waitstream(chan, AST_DIGIT_ANY); 00580 ast_stopstream(chan); 00581 if (!res) 00582 res = ast_waitfordigit(chan, 5000); 00583 if (res > 0) { 00584 res = do_directory(chan, cfg, context, dialcontext, res, last); 00585 if (res > 0) { 00586 res = ast_waitstream(chan, AST_DIGIT_ANY); 00587 ast_stopstream(chan); 00588 if (res >= 0) { 00589 continue; 00590 } 00591 } 00592 } 00593 break; 00594 } 00595 ast_config_destroy(cfg); 00596 LOCAL_USER_REMOVE(u); 00597 return res; 00598 }
|
|
Definition at line 406 of file app_directory.c. References ast_goto_if_exists(), ast_log(), ast_readstring(), ast_streamfile(), ast_strlen_zero(), ast_variable_browse(), ast_channel::context, convert(), free, ast_channel::language, LOG_WARNING, ast_channel::macrocontext, ast_variable::name, name, ast_variable::next, NUMDIGITS, play_mailbox_owner(), strcasestr(), strdup, strsep(), and ast_variable::value. Referenced by directory_exec(). 00407 { 00408 /* Read in the first three digits.. "digit" is the first digit, already read */ 00409 char ext[NUMDIGITS + 1]; 00410 char name[80] = ""; 00411 struct ast_variable *v; 00412 int res; 00413 int found=0; 00414 int lastuserchoice = 0; 00415 char *start, *pos, *conv,*stringp=NULL; 00416 00417 if (ast_strlen_zero(context)) { 00418 ast_log(LOG_WARNING, 00419 "Directory must be called with an argument " 00420 "(context in which to interpret extensions)\n"); 00421 return -1; 00422 } 00423 if (digit == '0') { 00424 if (!ast_goto_if_exists(chan, chan->context, "o", 1) || 00425 (!ast_strlen_zero(chan->macrocontext) && 00426 !ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) { 00427 return 0; 00428 } else { 00429 ast_log(LOG_WARNING, "Can't find extension 'o' in current context. " 00430 "Not Exiting the Directory!\n"); 00431 res = 0; 00432 } 00433 } 00434 if (digit == '*') { 00435 if (!ast_goto_if_exists(chan, chan->context, "a", 1) || 00436 (!ast_strlen_zero(chan->macrocontext) && 00437 !ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) { 00438 return 0; 00439 } else { 00440 ast_log(LOG_WARNING, "Can't find extension 'a' in current context. " 00441 "Not Exiting the Directory!\n"); 00442 res = 0; 00443 } 00444 } 00445 memset(ext, 0, sizeof(ext)); 00446 ext[0] = digit; 00447 res = 0; 00448 if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1; 00449 if (!res) { 00450 /* Search for all names which start with those digits */ 00451 v = ast_variable_browse(cfg, context); 00452 while(v && !res) { 00453 /* Find all candidate extensions */ 00454 while(v) { 00455 /* Find a candidate extension */ 00456 start = strdup(v->value); 00457 if (start && !strcasestr(start, "hidefromdir=yes")) { 00458 stringp=start; 00459 strsep(&stringp, ","); 00460 pos = strsep(&stringp, ","); 00461 if (pos) { 00462 ast_copy_string(name, pos, sizeof(name)); 00463 /* Grab the last name */ 00464 if (last && strrchr(pos,' ')) 00465 pos = strrchr(pos, ' ') + 1; 00466 conv = convert(pos); 00467 if (conv) { 00468 if (!strcmp(conv, ext)) { 00469 /* Match! */ 00470 found++; 00471 free(conv); 00472 free(start); 00473 break; 00474 } 00475 free(conv); 00476 } 00477 } 00478 free(start); 00479 } 00480 v = v->next; 00481 } 00482 00483 if (v) { 00484 /* We have a match -- play a greeting if they have it */ 00485 res = play_mailbox_owner(chan, context, dialcontext, v->name, name); 00486 switch (res) { 00487 case -1: 00488 /* user pressed '1' but extension does not exist, or 00489 * user hungup 00490 */ 00491 lastuserchoice = 0; 00492 break; 00493 case '1': 00494 /* user pressed '1' and extensions exists; 00495 play_mailbox_owner will already have done 00496 a goto() on the channel 00497 */ 00498 lastuserchoice = res; 00499 break; 00500 case '*': 00501 /* user pressed '*' to skip something found */ 00502 lastuserchoice = res; 00503 res = 0; 00504 break; 00505 default: 00506 break; 00507 } 00508 v = v->next; 00509 } 00510 } 00511 00512 if (lastuserchoice != '1') { 00513 if (found) 00514 res = ast_streamfile(chan, "dir-nomore", chan->language); 00515 else 00516 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00517 if (!res) 00518 res = 1; 00519 return res; 00520 } 00521 return 0; 00522 } 00523 return res; 00524 }
|
|
Returns the ASTERISK_GPL_KEY. This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 647 of file app_directory.c. References ASTERISK_GPL_KEY. 00648 { 00649 return ASTERISK_GPL_KEY; 00650 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 611 of file app_directory.c. References app, ast_config_destroy(), ast_config_load(), ast_log(), ast_register_application(), ast_variable_retrieve(), cfg, descrip, directory_exec(), LOG_WARNING, synopsis, vmfmts, and VOICEMAIL_CONFIG. 00612 { 00613 #ifdef USE_ODBC_STORAGE 00614 struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG); 00615 char *tmp; 00616 00617 if (cfg) { 00618 if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) { 00619 ast_copy_string(odbc_database, tmp, sizeof(odbc_database)); 00620 } 00621 if ((tmp = ast_variable_retrieve(cfg, "general", "odbctable"))) { 00622 ast_copy_string(odbc_table, tmp, sizeof(odbc_table)); 00623 } 00624 if ((tmp = ast_variable_retrieve(cfg, "general", "format"))) { 00625 ast_copy_string(vmfmts, tmp, sizeof(vmfmts)); 00626 } 00627 ast_config_destroy(cfg); 00628 } else 00629 ast_log(LOG_WARNING, "Unable to load " VOICEMAIL_CONFIG " - ODBC defaults will be used\n"); 00630 #endif 00631 00632 return ast_register_application(app, directory_exec, synopsis, descrip); 00633 }
|
|
Definition at line 259 of file app_directory.c. References ast_config_AST_SPOOL_DIR, AST_DIGIT_ANY, ast_filedelete(), ast_fileexists(), ast_goto_if_exists(), ast_log(), ast_say_character_str(), ast_stopstream(), ast_streamfile(), ast_strlen_zero(), ast_waitfordigit(), ast_waitstream(), ast_channel::language, and LOG_WARNING. Referenced by do_directory(). 00259 { 00260 int res = 0; 00261 int loop = 3; 00262 char fn[256]; 00263 char fn2[256]; 00264 00265 /* Check for the VoiceMail2 greeting first */ 00266 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", 00267 (char *)ast_config_AST_SPOOL_DIR, context, ext); 00268 #ifdef USE_ODBC_STORAGE 00269 retrieve_file(fn); 00270 #endif 00271 00272 /* Otherwise, check for an old-style Voicemail greeting */ 00273 snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", 00274 (char *)ast_config_AST_SPOOL_DIR, ext); 00275 #ifdef USE_ODBC_STORAGE 00276 retrieve_file(fn2); 00277 #endif 00278 00279 if (ast_fileexists(fn, NULL, chan->language) > 0) { 00280 res = ast_streamfile(chan, fn, chan->language); 00281 if (!res) { 00282 res = ast_waitstream(chan, AST_DIGIT_ANY); 00283 } 00284 ast_stopstream(chan); 00285 } else if (ast_fileexists(fn2, NULL, chan->language) > 0) { 00286 res = ast_streamfile(chan, fn2, chan->language); 00287 if (!res) { 00288 res = ast_waitstream(chan, AST_DIGIT_ANY); 00289 } 00290 ast_stopstream(chan); 00291 } else { 00292 res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext, 00293 AST_DIGIT_ANY, chan->language); 00294 } 00295 #ifdef USE_ODBC_STORAGE 00296 ast_filedelete(fn, NULL); 00297 ast_filedelete(fn2, NULL); 00298 #endif 00299 00300 while (loop) { 00301 if (!res) { 00302 res = ast_streamfile(chan, "dir-instr", chan->language); 00303 } 00304 if (!res) { 00305 res = ast_waitstream(chan, AST_DIGIT_ANY); 00306 } 00307 if (!res) { 00308 res = ast_waitfordigit(chan, 3000); 00309 } 00310 ast_stopstream(chan); 00311 00312 if (res > -1) { 00313 switch (res) { 00314 case '1': 00315 /* Name selected */ 00316 loop = 0; 00317 if (ast_goto_if_exists(chan, dialcontext, ext, 1)) { 00318 ast_log(LOG_WARNING, 00319 "Can't find extension '%s' in context '%s'. " 00320 "Did you pass the wrong context to Directory?\n", 00321 ext, dialcontext); 00322 res = -1; 00323 } 00324 break; 00325 00326 case '*': 00327 /* Skip to next match in list */ 00328 loop = 0; 00329 break; 00330 00331 default: 00332 /* Not '1', or '*', so decrement number of tries */ 00333 res = 0; 00334 loop--; 00335 break; 00336 } /* end switch */ 00337 } /* end if */ 00338 else { 00339 /* User hungup, so jump out now */ 00340 loop = 0; 00341 } 00342 } /* end while */ 00343 00344 return(res); 00345 }
|
|
Definition at line 347 of file app_directory.c. References ast_category_append(), ast_category_browse(), ast_category_get(), ast_category_new(), ast_config_destroy(), ast_config_load(), ast_load_realtime_multientry(), ast_log(), ast_variable_append(), ast_variable_new(), ast_variable_retrieve(), cfg, LOG_WARNING, mailbox, var, and VOICEMAIL_CONFIG. Referenced by directory_exec(). 00348 { 00349 struct ast_config *cfg; 00350 struct ast_config *rtdata; 00351 struct ast_category *cat; 00352 struct ast_variable *var; 00353 char *mailbox; 00354 char *fullname; 00355 char *hidefromdir; 00356 char tmp[100]; 00357 00358 /* Load flat file config. */ 00359 cfg = ast_config_load(VOICEMAIL_CONFIG); 00360 00361 if (!cfg) { 00362 /* Loading config failed. */ 00363 ast_log(LOG_WARNING, "Loading config failed.\n"); 00364 return NULL; 00365 } 00366 00367 /* Get realtime entries, categorized by their mailbox number 00368 and present in the requested context */ 00369 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL); 00370 00371 /* if there are no results, just return the entries from the config file */ 00372 if (!rtdata) 00373 return cfg; 00374 00375 /* Does the context exist within the config file? If not, make one */ 00376 cat = ast_category_get(cfg, context); 00377 if (!cat) { 00378 cat = ast_category_new(context); 00379 if (!cat) { 00380 ast_log(LOG_WARNING, "Out of memory\n"); 00381 ast_config_destroy(cfg); 00382 return NULL; 00383 } 00384 ast_category_append(cfg, cat); 00385 } 00386 00387 mailbox = ast_category_browse(rtdata, NULL); 00388 while (mailbox) { 00389 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00390 hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir"); 00391 snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s", 00392 fullname ? fullname : "", 00393 hidefromdir ? hidefromdir : "no"); 00394 var = ast_variable_new(mailbox, tmp); 00395 if (var) 00396 ast_variable_append(cat, var); 00397 else 00398 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00399 mailbox = ast_category_browse(rtdata, mailbox); 00400 } 00401 ast_config_destroy(rtdata); 00402 00403 return cfg; 00404 }
|
|
Cleanup all module structures, sockets, etc. This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 600 of file app_directory.c. References app, ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS. 00601 { 00602 int res; 00603 00604 res = ast_unregister_application(app); 00605 00606 STANDARD_HANGUP_LOCALUSERS; 00607 00608 return res; 00609 }
|
|
Provides a usecount. This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 640 of file app_directory.c. References STANDARD_USECOUNT. 00641 { 00642 int res; 00643 STANDARD_USECOUNT(res); 00644 return res; 00645 }
|
|
Definition at line 56 of file app_directory.c. |
|
Definition at line 59 of file app_directory.c. |
|
Definition at line 88 of file app_directory.c. |
|
Definition at line 86 of file app_directory.c. |
|
Definition at line 58 of file app_directory.c. |
|
Definition at line 55 of file app_directory.c. |