#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 | |
char * | convert (char *lastname) |
char * | description (void) |
Provides a description of the module. | |
int | directory_exec (struct ast_channel *chan, void *data) |
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. | |
int | play_mailbox_owner (struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name) |
ast_config * | realtime_directory (char *context) |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
char * | app = "Directory" |
char * | descrip |
LOCAL_USER_DECL | |
STANDARD_LOCAL_USER | |
char * | synopsis = "Provide directory of voicemail extensions" |
char * | tdesc = "Extension Directory" |
Definition in file app_directory.c.
|
Definition at line 74 of file app_directory.c. Referenced by convert(), and do_directory(). |
|
Definition at line 71 of file app_directory.c. Referenced by load_config(), and realtime_directory(). |
|
Definition at line 80 of file app_directory.c. References malloc, and NUMDIGITS. Referenced by do_directory(). 00081 { 00082 char *tmp; 00083 int lcount = 0; 00084 tmp = malloc(NUMDIGITS + 1); 00085 if (tmp) { 00086 while((*lastname > 32) && lcount < NUMDIGITS) { 00087 switch(toupper(*lastname)) { 00088 case '1': 00089 tmp[lcount++] = '1'; 00090 break; 00091 case '2': 00092 case 'A': 00093 case 'B': 00094 case 'C': 00095 tmp[lcount++] = '2'; 00096 break; 00097 case '3': 00098 case 'D': 00099 case 'E': 00100 case 'F': 00101 tmp[lcount++] = '3'; 00102 break; 00103 case '4': 00104 case 'G': 00105 case 'H': 00106 case 'I': 00107 tmp[lcount++] = '4'; 00108 break; 00109 case '5': 00110 case 'J': 00111 case 'K': 00112 case 'L': 00113 tmp[lcount++] = '5'; 00114 break; 00115 case '6': 00116 case 'M': 00117 case 'N': 00118 case 'O': 00119 tmp[lcount++] = '6'; 00120 break; 00121 case '7': 00122 case 'P': 00123 case 'Q': 00124 case 'R': 00125 case 'S': 00126 tmp[lcount++] = '7'; 00127 break; 00128 case '8': 00129 case 'T': 00130 case 'U': 00131 case 'V': 00132 tmp[lcount++] = '8'; 00133 break; 00134 case '9': 00135 case 'W': 00136 case 'X': 00137 case 'Y': 00138 case 'Z': 00139 tmp[lcount++] = '9'; 00140 break; 00141 } 00142 lastname++; 00143 } 00144 tmp[lcount] = '\0'; 00145 } 00146 return tmp; 00147 }
|
|
Provides a description of the module.
Definition at line 501 of file app_directory.c. 00502 {
00503 return tdesc;
00504 }
|
|
Definition at line 411 of file app_directory.c. References ast_channel::_state, ast_answer(), ast_config_destroy(), AST_DIGIT_ANY, ast_log(), ast_stopstream(), ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_variable_retrieve(), ast_waitfordigit(), ast_waitstream(), cfg, do_directory(), ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, and realtime_directory(). Referenced by load_module(). 00412 { 00413 int res = 0; 00414 struct localuser *u; 00415 struct ast_config *cfg; 00416 int last = 1; 00417 char *context, *dialcontext, *dirintro, *options; 00418 00419 if (ast_strlen_zero(data)) { 00420 ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n"); 00421 return -1; 00422 } 00423 00424 LOCAL_USER_ADD(u); 00425 00426 context = ast_strdupa(data); 00427 dialcontext = strchr(context, '|'); 00428 if (dialcontext) { 00429 *dialcontext = '\0'; 00430 dialcontext++; 00431 options = strchr(dialcontext, '|'); 00432 if (options) { 00433 *options = '\0'; 00434 options++; 00435 if (strchr(options, 'f')) 00436 last = 0; 00437 } 00438 } else 00439 dialcontext = context; 00440 00441 cfg = realtime_directory(context); 00442 if (!cfg) { 00443 LOCAL_USER_REMOVE(u); 00444 return -1; 00445 } 00446 00447 dirintro = ast_variable_retrieve(cfg, context, "directoryintro"); 00448 if (ast_strlen_zero(dirintro)) 00449 dirintro = ast_variable_retrieve(cfg, "general", "directoryintro"); 00450 if (ast_strlen_zero(dirintro)) { 00451 if (last) 00452 dirintro = "dir-intro"; 00453 else 00454 dirintro = "dir-intro-fn"; 00455 } 00456 00457 if (chan->_state != AST_STATE_UP) 00458 res = ast_answer(chan); 00459 00460 for (;;) { 00461 if (!res) 00462 res = ast_streamfile(chan, dirintro, chan->language); 00463 if (!res) 00464 res = ast_waitstream(chan, AST_DIGIT_ANY); 00465 ast_stopstream(chan); 00466 if (!res) 00467 res = ast_waitfordigit(chan, 5000); 00468 if (res > 0) { 00469 res = do_directory(chan, cfg, context, dialcontext, res, last); 00470 if (res > 0) { 00471 res = ast_waitstream(chan, AST_DIGIT_ANY); 00472 ast_stopstream(chan); 00473 if (res >= 0) { 00474 continue; 00475 } 00476 } 00477 } 00478 break; 00479 } 00480 ast_config_destroy(cfg); 00481 LOCAL_USER_REMOVE(u); 00482 return res; 00483 }
|
|
Definition at line 291 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_variable::name, name, ast_variable::next, NUMDIGITS, play_mailbox_owner(), strcasestr(), strdup, strsep(), and ast_variable::value. Referenced by directory_exec(). 00292 { 00293 /* Read in the first three digits.. "digit" is the first digit, already read */ 00294 char ext[NUMDIGITS + 1]; 00295 char name[80] = ""; 00296 struct ast_variable *v; 00297 int res; 00298 int found=0; 00299 int lastuserchoice = 0; 00300 char *start, *pos, *conv,*stringp=NULL; 00301 00302 if (ast_strlen_zero(context)) { 00303 ast_log(LOG_WARNING, 00304 "Directory must be called with an argument " 00305 "(context in which to interpret extensions)\n"); 00306 return -1; 00307 } 00308 if (digit == '0') { 00309 if (!ast_goto_if_exists(chan, chan->context, "o", 1) || 00310 (!ast_strlen_zero(chan->macrocontext) && 00311 !ast_goto_if_exists(chan, chan->macrocontext, "o", 1))) { 00312 return 0; 00313 } else { 00314 ast_log(LOG_WARNING, "Can't find extension 'o' in current context. " 00315 "Not Exiting the Directory!\n"); 00316 res = 0; 00317 } 00318 } 00319 if (digit == '*') { 00320 if (!ast_goto_if_exists(chan, chan->context, "a", 1) || 00321 (!ast_strlen_zero(chan->macrocontext) && 00322 !ast_goto_if_exists(chan, chan->macrocontext, "a", 1))) { 00323 return 0; 00324 } else { 00325 ast_log(LOG_WARNING, "Can't find extension 'a' in current context. " 00326 "Not Exiting the Directory!\n"); 00327 res = 0; 00328 } 00329 } 00330 memset(ext, 0, sizeof(ext)); 00331 ext[0] = digit; 00332 res = 0; 00333 if (ast_readstring(chan, ext + 1, NUMDIGITS - 1, 3000, 3000, "#") < 0) res = -1; 00334 if (!res) { 00335 /* Search for all names which start with those digits */ 00336 v = ast_variable_browse(cfg, context); 00337 while(v && !res) { 00338 /* Find all candidate extensions */ 00339 while(v) { 00340 /* Find a candidate extension */ 00341 start = strdup(v->value); 00342 if (start && !strcasestr(start, "hidefromdir=yes")) { 00343 stringp=start; 00344 strsep(&stringp, ","); 00345 pos = strsep(&stringp, ","); 00346 if (pos) { 00347 ast_copy_string(name, pos, sizeof(name)); 00348 /* Grab the last name */ 00349 if (last && strrchr(pos,' ')) 00350 pos = strrchr(pos, ' ') + 1; 00351 conv = convert(pos); 00352 if (conv) { 00353 if (!strcmp(conv, ext)) { 00354 /* Match! */ 00355 found++; 00356 free(conv); 00357 free(start); 00358 break; 00359 } 00360 free(conv); 00361 } 00362 } 00363 free(start); 00364 } 00365 v = v->next; 00366 } 00367 00368 if (v) { 00369 /* We have a match -- play a greeting if they have it */ 00370 res = play_mailbox_owner(chan, context, dialcontext, v->name, name); 00371 switch (res) { 00372 case -1: 00373 /* user pressed '1' but extension does not exist, or 00374 * user hungup 00375 */ 00376 lastuserchoice = 0; 00377 break; 00378 case '1': 00379 /* user pressed '1' and extensions exists; 00380 play_mailbox_owner will already have done 00381 a goto() on the channel 00382 */ 00383 lastuserchoice = res; 00384 break; 00385 case '*': 00386 /* user pressed '*' to skip something found */ 00387 lastuserchoice = res; 00388 res = 0; 00389 break; 00390 default: 00391 break; 00392 } 00393 v = v->next; 00394 } 00395 } 00396 00397 if (lastuserchoice != '1') { 00398 if (found) 00399 res = ast_streamfile(chan, "dir-nomore", chan->language); 00400 else 00401 res = ast_streamfile(chan, "dir-nomatch", chan->language); 00402 if (!res) 00403 res = 1; 00404 return res; 00405 } 00406 return 0; 00407 } 00408 return res; 00409 }
|
|
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 513 of file app_directory.c. 00514 {
00515 return ASTERISK_GPL_KEY;
00516 }
|
|
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 496 of file app_directory.c. References app, ast_register_application(), descrip, directory_exec(), and synopsis. 00497 { 00498 return ast_register_application(app, directory_exec, synopsis, descrip); 00499 }
|
|
Definition at line 154 of file app_directory.c. References ast_config_AST_SPOOL_DIR, AST_DIGIT_ANY, 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, LOG_WARNING, and name. Referenced by do_directory(). 00154 { 00155 int res = 0; 00156 int loop = 3; 00157 char fn[256]; 00158 char fn2[256]; 00159 00160 /* Check for the VoiceMail2 greeting first */ 00161 snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", 00162 (char *)ast_config_AST_SPOOL_DIR, context, ext); 00163 00164 /* Otherwise, check for an old-style Voicemail greeting */ 00165 snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet", 00166 (char *)ast_config_AST_SPOOL_DIR, ext); 00167 00168 if (ast_fileexists(fn, NULL, chan->language) > 0) { 00169 res = ast_streamfile(chan, fn, chan->language); 00170 if (!res) { 00171 res = ast_waitstream(chan, AST_DIGIT_ANY); 00172 } 00173 ast_stopstream(chan); 00174 } else if (ast_fileexists(fn2, NULL, chan->language) > 0) { 00175 res = ast_streamfile(chan, fn2, chan->language); 00176 if (!res) { 00177 res = ast_waitstream(chan, AST_DIGIT_ANY); 00178 } 00179 ast_stopstream(chan); 00180 } else { 00181 res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext, 00182 AST_DIGIT_ANY, chan->language); 00183 } 00184 00185 while (loop) { 00186 if (!res) { 00187 res = ast_streamfile(chan, "dir-instr", chan->language); 00188 } 00189 if (!res) { 00190 res = ast_waitstream(chan, AST_DIGIT_ANY); 00191 } 00192 if (!res) { 00193 res = ast_waitfordigit(chan, 3000); 00194 } 00195 ast_stopstream(chan); 00196 00197 if (res > -1) { 00198 switch (res) { 00199 case '1': 00200 /* Name selected */ 00201 loop = 0; 00202 if (ast_goto_if_exists(chan, dialcontext, ext, 1)) { 00203 ast_log(LOG_WARNING, 00204 "Can't find extension '%s' in context '%s'. " 00205 "Did you pass the wrong context to Directory?\n", 00206 ext, dialcontext); 00207 res = -1; 00208 } 00209 break; 00210 00211 case '*': 00212 /* Skip to next match in list */ 00213 loop = 0; 00214 break; 00215 00216 default: 00217 /* Not '1', or '*', so decrement number of tries */ 00218 res = 0; 00219 loop--; 00220 break; 00221 } /* end switch */ 00222 } /* end if */ 00223 else { 00224 /* User hungup, so jump out now */ 00225 loop = 0; 00226 } 00227 } /* end while */ 00228 00229 return(res); 00230 }
|
|
Definition at line 232 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, var, and VOICEMAIL_CONFIG. Referenced by directory_exec(). 00233 { 00234 struct ast_config *cfg; 00235 struct ast_config *rtdata; 00236 struct ast_category *cat; 00237 struct ast_variable *var; 00238 char *mailbox; 00239 char *fullname; 00240 char *hidefromdir; 00241 char tmp[100]; 00242 00243 /* Load flat file config. */ 00244 cfg = ast_config_load(VOICEMAIL_CONFIG); 00245 00246 if (!cfg) { 00247 /* Loading config failed. */ 00248 ast_log(LOG_WARNING, "Loading config failed.\n"); 00249 return NULL; 00250 } 00251 00252 /* Get realtime entries, categorized by their mailbox number 00253 and present in the requested context */ 00254 rtdata = ast_load_realtime_multientry("voicemail", "mailbox LIKE", "%", "context", context, NULL); 00255 00256 /* if there are no results, just return the entries from the config file */ 00257 if (!rtdata) 00258 return cfg; 00259 00260 /* Does the context exist within the config file? If not, make one */ 00261 cat = ast_category_get(cfg, context); 00262 if (!cat) { 00263 cat = ast_category_new(context); 00264 if (!cat) { 00265 ast_log(LOG_WARNING, "Out of memory\n"); 00266 ast_config_destroy(cfg); 00267 return NULL; 00268 } 00269 ast_category_append(cfg, cat); 00270 } 00271 00272 mailbox = ast_category_browse(rtdata, NULL); 00273 while (mailbox) { 00274 fullname = ast_variable_retrieve(rtdata, mailbox, "fullname"); 00275 hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir"); 00276 snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s", 00277 fullname ? fullname : "", 00278 hidefromdir ? hidefromdir : "no"); 00279 var = ast_variable_new(mailbox, tmp); 00280 if (var) 00281 ast_variable_append(cat, var); 00282 else 00283 ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox); 00284 mailbox = ast_category_browse(rtdata, mailbox); 00285 } 00286 ast_config_destroy(rtdata); 00287 00288 return cfg; 00289 }
|
|
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 485 of file app_directory.c. References app, and ast_unregister_application(). 00486 { 00487 int res; 00488 00489 res = ast_unregister_application(app); 00490 00491 STANDARD_HANGUP_LOCALUSERS; 00492 00493 return res; 00494 }
|
|
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 506 of file app_directory.c. References STANDARD_USECOUNT. 00507 { 00508 int res; 00509 STANDARD_USECOUNT(res); 00510 return res; 00511 }
|
|
Definition at line 46 of file app_directory.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 49 of file app_directory.c. Referenced by load_module(). |
|
Definition at line 78 of file app_directory.c. |
|
Definition at line 76 of file app_directory.c. |
|
Definition at line 48 of file app_directory.c. Referenced by load_module(). |
|
Definition at line 45 of file app_directory.c. |