#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"
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, int fromappvm) |
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, int fromappvm) |
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.
#define NUMDIGITS 3 |
#define VOICEMAIL_CONFIG "voicemail.conf" |
Definition at line 81 of file app_directory.c.
Referenced by load_config(), load_module(), and realtime_directory().
static char* convert | ( | char * | lastname | ) | [static] |
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 }
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 643 of file app_directory.c.
00644 { 00645 return tdesc; 00646 }
static int directory_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 531 of file app_directory.c.
References ast_channel::_state, 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(), ast_channel::language, last, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, and realtime_directory().
Referenced by load_module().
00532 { 00533 int res = 0; 00534 struct localuser *u; 00535 struct ast_config *cfg; 00536 int last = 1; 00537 int fromappvm = 0; 00538 char *context, *dialcontext, *dirintro, *options; 00539 00540 if (ast_strlen_zero(data)) { 00541 ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n"); 00542 return -1; 00543 } 00544 00545 LOCAL_USER_ADD(u); 00546 00547 context = ast_strdupa(data); 00548 dialcontext = strchr(context, '|'); 00549 if (dialcontext) { 00550 *dialcontext = '\0'; 00551 dialcontext++; 00552 options = strchr(dialcontext, '|'); 00553 if (options) { 00554 *options = '\0'; 00555 options++; 00556 if (strchr(options, 'f')) 00557 last = 0; 00558 if (strchr(options, 'v')) 00559 fromappvm = 1; 00560 } 00561 } else 00562 dialcontext = context; 00563 00564 cfg = realtime_directory(context); 00565 if (!cfg) { 00566 LOCAL_USER_REMOVE(u); 00567 return -1; 00568 } 00569 00570 dirintro = ast_variable_retrieve(cfg, context, "directoryintro"); 00571 if (ast_strlen_zero(dirintro)) 00572 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00573 if (ast_strlen_zero(dirintro)) { 00574 if (last) 00575 dirintro = "dir-intro"; 00576 else 00577 dirintro = "dir-intro-fn"; 00578 } 00579 00580 if (chan->_state != AST_STATE_UP) 00581 res = ast_answer(chan); 00582 00583 for (;;) { 00584 if (!res) 00585 res = ast_streamfile(chan, dirintro, chan->language); 00586 if (!res) 00587 res = ast_waitstream(chan, AST_DIGIT_ANY); 00588 ast_stopstream(chan); 00589 if (!res) 00590 res = ast_waitfordigit(chan, 5000); 00591 if (res > 0) { 00592 res = do_directory(chan, cfg, context, dialcontext, res, last, fromappvm); 00593 if (res > 0) { 00594 res = ast_waitstream(chan, AST_DIGIT_ANY); 00595 ast_stopstream(chan); 00596 if (res >= 0) { 00597 continue; 00598 } 00599 } 00600 } 00601 break; 00602 } 00603 ast_config_destroy(cfg); 00604 LOCAL_USER_REMOVE(u); 00605 return res; 00606 }
static int do_directory | ( | struct ast_channel * | chan, | |
struct ast_config * | cfg, | |||
char * | context, | |||
char * | dialcontext, | |||
char | digit, | |||
int | last, | |||
int | fromappvm | |||
) | [static] |
Definition at line 411 of file app_directory.c.
References ast_goto_if_exists(), ast_log(), ast_readstring(), ast_streamfile(), ast_strlen_zero(), ast_variable_browse(), cfg, ast_channel::context, convert(), free, ast_channel::language, LOG_WARNING, ast_channel::macrocontext, ast_channel::name, name, NUMDIGITS, play_mailbox_owner(), strcasestr(), strdup, and strsep().
Referenced by directory_exec().
00412 { 00413 /* Read in the first three digits.. "digit" is the first digit, already read */ 00414 char ext[NUMDIGITS + 1]; 00415 char name[80] = ""; 00416 struct ast_variable *v; 00417 int res; 00418 int found=0; 00419 int lastuserchoice = 0; 00420 char *start, *pos, *conv,*stringp=NULL; 00421 00422 if (ast_strlen_zero(context)) { 00423 ast_log(LOG_WARNING, 00424 "Directory must be called with an argument " 00425 "(context in which to interpret extensions)\n"); 00426 return -1; 00427 } 00428 if (digit == '0') { 00429 if (!ast_goto_if_exists(chan, chan->context, "o", 1) || 00430 (!ast_strlen_zero(chan->macrocontext) && 00431 !ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) { 00432 return 0; 00433 } else { 00434 ast_log(LOG_WARNING, "Can't find extension 'o' in current context. " 00435 "Not Exiting the Directory!\n"); 00436 res = 0; 00437 } 00438 } 00439 if (digit == '*') { 00440 if (!ast_goto_if_exists(chan, chan->context, "a", 1) || 00441 (!ast_strlen_zero(chan->macrocontext) && 00442 !ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) { 00443 return 0; 00444 } else { 00445 ast_log(LOG_WARNING, "Can't find extension 'a' in current context. " 00446 "Not Exiting the Directory!\n"); 00447 res = 0; 00448 } 00449 } 00450 memset(ext, 0, sizeof(ext)); 00451 ext[0] = digit; 00452 res = 0; 00453 if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1; 00454 if (!res) { 00455 /* Search for all names which start with those digits */ 00456 v = ast_variable_browse(cfg, context); 00457 while(v && !res) { 00458 /* Find all candidate extensions */ 00459 while(v) { 00460 /* Find a candidate extension */ 00461 start = strdup(v->value); 00462 if (start && !strcasestr(start, "hidefromdir=yes")) { 00463 stringp=start; 00464 strsep(&stringp, ","); 00465 pos = strsep(&stringp, ","); 00466 if (pos) { 00467 ast_copy_string(name, pos, sizeof(name)); 00468 /* Grab the last name */ 00469 if (last && strrchr(pos,' ')) 00470 pos = strrchr(pos, ' ') + 1; 00471 conv = convert(pos); 00472 if (conv) { 00473 if (!strcmp(conv, ext)) { 00474 /* Match! */ 00475 found++; 00476 free(conv); 00477 free(start); 00478 break; 00479 } 00480 free(conv); 00481 } 00482 } 00483 free(start); 00484 } 00485 v = v->next; 00486 } 00487 00488 if (v) { 00489 /* We have a match -- play a greeting if they have it */ 00490 res = play_mailbox_owner(chan, context, dialcontext, v->name, name, fromappvm); 00491 switch (res) { 00492 case -1: 00493 /* user pressed '1' but extension does not exist, or 00494 * user hungup 00495 */ 00496 lastuserchoice = 0; 00497 break; 00498 case '1': 00499 /* user pressed '1' and extensions exists; 00500 play_mailbox_owner will already have done 00501 a goto() on the channel 00502 */ 00503 lastuserchoice = res; 00504 break; 00505 case '*': 00506 /* user pressed '*' to skip something found */ 00507 lastuserchoice = res; 00508 res = 0; 00509 break; 00510 default: 00511 break; 00512 } 00513 v = v->next; 00514 } 00515 } 00516 00517 if (lastuserchoice != '1') { 00518 if (found) 00519 res = ast_streamfile(chan, "dir-nomore", chan->language); 00520 else 00521 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00522 if (!res) 00523 res = 1; 00524 return res; 00525 } 00526 return 0; 00527 } 00528 return res; 00529 }
char* key | ( | void | ) |
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 655 of file app_directory.c.
References ASTERISK_GPL_KEY.
00656 { 00657 return ASTERISK_GPL_KEY; 00658 }
int load_module | ( | void | ) |
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 619 of file app_directory.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_register_application(), ast_variable_retrieve(), cfg, directory_exec(), LOG_WARNING, and VOICEMAIL_CONFIG.
00620 { 00621 #ifdef USE_ODBC_STORAGE 00622 struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG); 00623 char *tmp; 00624 00625 if (cfg) { 00626 if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) { 00627 ast_copy_string(odbc_database, tmp, sizeof(odbc_database)); 00628 } 00629 if ((tmp = ast_variable_retrieve(cfg, "general", "odbctable"))) { 00630 ast_copy_string(odbc_table, tmp, sizeof(odbc_table)); 00631 } 00632 if ((tmp = ast_variable_retrieve(cfg, "general", "format"))) { 00633 ast_copy_string(vmfmts, tmp, sizeof(vmfmts)); 00634 } 00635 ast_config_destroy(cfg); 00636 } else 00637 ast_log(LOG_WARNING, "Unable to load " VOICEMAIL_CONFIG " - ODBC defaults will be used\n"); 00638 #endif 00639 00640 return ast_register_application(app, directory_exec, synopsis, descrip); 00641 }
static int play_mailbox_owner | ( | struct ast_channel * | chan, | |
char * | context, | |||
char * | dialcontext, | |||
char * | ext, | |||
char * | name, | |||
int | fromappvm | |||
) | [static] |
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::exten, 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 (fromappvm) { 00318 /* We still want to set the exten */ 00319 ast_copy_string(chan->exten, ext, sizeof(chan->exten)); 00320 } else { 00321 if (ast_goto_if_exists(chan, dialcontext, ext, 1)) { 00322 ast_log(LOG_WARNING, 00323 "Can't find extension '%s' in context '%s'. " 00324 "Did you pass the wrong context to Directory?\n", 00325 ext, dialcontext); 00326 res = -1; 00327 } 00328 } 00329 break; 00330 00331 case '*': 00332 /* Skip to next match in list */ 00333 loop = 0; 00334 break; 00335 00336 default: 00337 /* Not '1', or '*', so decrement number of tries */ 00338 res = 0; 00339 loop--; 00340 break; 00341 } /* end switch */ 00342 } /* end if */ 00343 else { 00344 /* User hungup, so jump out now */ 00345 loop = 0; 00346 } 00347 } /* end while */ 00348 00349 return(res); 00350 }
static struct ast_config* realtime_directory | ( | char * | context | ) | [static] |
Definition at line 352 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().
00353 { 00354 struct ast_config *cfg; 00355 struct ast_config *rtdata; 00356 struct ast_category *cat; 00357 struct ast_variable *var; 00358 char *mailbox; 00359 char *fullname; 00360 char *hidefromdir; 00361 char tmp[100]; 00362 00363 /* Load flat file config. */ 00364 cfg = ast_config_load(VOICEMAIL_CONFIG); 00365 00366 if (!cfg) { 00367 /* Loading config failed. */ 00368 ast_log(LOG_WARNING, "Loading config failed.\n"); 00369 return NULL; 00370 } 00371 00372 /* Get realtime entries, categorized by their mailbox number 00373 and present in the requested context */ 00374 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL); 00375 00376 /* if there are no results, just return the entries from the config file */ 00377 if (!rtdata) 00378 return cfg; 00379 00380 /* Does the context exist within the config file? If not, make one */ 00381 cat = ast_category_get(cfg, context); 00382 if (!cat) { 00383 cat = ast_category_new(context); 00384 if (!cat) { 00385 ast_log(LOG_WARNING, "Out of memory\n"); 00386 ast_config_destroy(cfg); 00387 return NULL; 00388 } 00389 ast_category_append(cfg, cat); 00390 } 00391 00392 mailbox = ast_category_browse(rtdata, NULL); 00393 while (mailbox) { 00394 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00395 hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir"); 00396 snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s", 00397 fullname ? fullname : "", 00398 hidefromdir ? hidefromdir : "no"); 00399 var = ast_variable_new(mailbox, tmp); 00400 if (var) 00401 ast_variable_append(cat, var); 00402 else 00403 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00404 mailbox = ast_category_browse(rtdata, mailbox); 00405 } 00406 ast_config_destroy(rtdata); 00407 00408 return cfg; 00409 }
int unload_module | ( | void | ) |
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 608 of file app_directory.c.
References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.
00609 { 00610 int res; 00611 00612 res = ast_unregister_application(app); 00613 00614 STANDARD_HANGUP_LOCALUSERS; 00615 00616 return res; 00617 }
int usecount | ( | void | ) |
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 648 of file app_directory.c.
References STANDARD_USECOUNT.
00649 { 00650 int res; 00651 STANDARD_USECOUNT(res); 00652 return res; 00653 }
char* app = "Directory" [static] |
Definition at line 56 of file app_directory.c.
char* descrip [static] |
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.
char* synopsis = "Provide directory of voicemail extensions" [static] |
Definition at line 58 of file app_directory.c.
char* tdesc = "Extension Directory" [static] |
Definition at line 55 of file app_directory.c.