diff --git a/apps/app_directory.c b/apps/app_directory.c new file mode 100755 index 0000000000000000000000000000000000000000..f7ec414879926258d10ed0e7c524a822fb68a372 --- /dev/null +++ b/apps/app_directory.c @@ -0,0 +1,264 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Provide a directory of extensions + * + * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#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 <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <pthread.h> +#include <stdio.h> +#include "../asterisk.h" + +static char *tdesc = "Extension Directory"; +static char *app = "Directory"; + +/* For simplicity, I'm keeping the format compatible with the voicemail config, + but i'm open to suggestions for isolating it */ + +#define DIRECTORY_CONFIG "voicemail.conf" + +/* How many digits to read in */ +#define NUMDIGITS 3 + +STANDARD_LOCAL_USER; + +LOCAL_USER_DECL; + +static char *convert(char *lastname) +{ + char *tmp; + int lcount = 0; + tmp = malloc(NUMDIGITS + 1); + if (tmp) { + while((*lastname > 32) && lcount < NUMDIGITS) { + switch(toupper(*lastname)) { + case '1': + tmp[lcount++] = '1'; + break; + case '2': + case 'A': + case 'B': + case 'C': + tmp[lcount++] = '2'; + break; + case '3': + case 'D': + case 'E': + case 'F': + tmp[lcount++] = '3'; + break; + case '4': + case 'G': + case 'H': + case 'I': + tmp[lcount++] = '4'; + break; + case '5': + case 'J': + case 'K': + case 'L': + tmp[lcount++] = '5'; + break; + case '6': + case 'M': + case 'N': + case 'O': + tmp[lcount++] = '6'; + break; + case '7': + case 'P': + case 'Q': + case 'R': + case 'S': + tmp[lcount++] = '7'; + break; + case '8': + case 'T': + case 'U': + case 'V': + tmp[lcount++] = '8'; + break; + case '9': + case 'W': + case 'X': + case 'Y': + case 'Z': + tmp[lcount++] = '9'; + break; + default: + } + lastname++; + } + tmp[lcount] = '\0'; + } + return tmp; +} + +static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char digit) +{ + /* Read in the first three digits.. "digit" is the first digit, already read */ + char ext[NUMDIGITS + 1]; + struct ast_variable *v; + int res; + int found=0; + char *start, *pos, *conv; + char fn[256]; + memset(ext, 0, sizeof(ext)); + ext[0] = digit; + res = ast_readstring(chan, ext + 1, NUMDIGITS, 3000, 3000, "#"); + if (!res) { + /* Search for all names which start with those digits */ + v = ast_variable_browse(cfg, context); + while(v && !res) { + /* Find all candidate extensions */ + while(v) { + /* Find a candidate extension */ + start = strdup(v->value); + if (start) { + strtok(start, ","); + pos = strtok(NULL, ","); + if (pos) { + /* Grab the last name */ + if (strrchr(pos, ' ')) + pos = strrchr(pos, ' ') + 1; + conv = convert(pos); + if (conv) { + if (!strcmp(conv, ext)) { + /* Match! */ + found++; + free(conv); + free(start); + break; + } + free(conv); + } + } + free(start); + } + v = v->next; + } + if (v) { + /* We have a match -- play a greeting if they have it */ + snprintf(fn, sizeof(fn), "%s/vm/%s/greet", AST_SPOOL_DIR, v->name); + if (ast_fileexists(fn, NULL)) { + res = ast_streamfile(chan, fn); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + ast_stopstream(chan); + } else { + res = ast_say_digit_str(chan, v->name); + } +ahem: + if (!res) + res = ast_streamfile(chan, "dir-instr"); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + if (!res) + res = ast_waitfordigit(chan, 3000); + ast_stopstream(chan); + if (res > -1) { + if (res == '1') { + strncpy(chan->exten, v->name, sizeof(chan->exten)); + chan->priority = 0; + strncpy(chan->context, context, sizeof(chan->context)); + res = 0; + break; + } else if (res == '*') { + res = 0; + v = v->next; + } else { + res = 0; + goto ahem; + } + } + } else { + if (found) + res = ast_streamfile(chan, "dir-nomore"); + else + res = ast_streamfile(chan, "dir-nomatch"); + if (!res) + res = 1; + return res; + } + } + + } + return res; +} + +static int directory_exec(struct ast_channel *chan, void *data) +{ + int res = 0; + struct localuser *u; + struct ast_config *cfg; + if (!data) { + ast_log(LOG_WARNING, "directory requires an argument (context)\n"); + return -1; + } + cfg = ast_load(DIRECTORY_CONFIG); + if (!cfg) { + ast_log(LOG_WARNING, "Unable to open directory configuration %s\n", DIRECTORY_CONFIG); + return -1; + } + LOCAL_USER_ADD(u); +top: + if (!res) + res = ast_streamfile(chan, "dir-intro"); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + ast_stopstream(chan); + if (!res) + res = ast_waitfordigit(chan, 5000); + if (res > 0) { + res = do_directory(chan, cfg, (char *)data, res); + if (res > 0) { + res = ast_waitstream(chan, AST_DIGIT_ANY); + ast_stopstream(chan); + if (res >= 0) { + goto top; + } + } + } + ast_destroy(cfg); + LOCAL_USER_REMOVE(u); + return res; +} + +int unload_module(void) +{ + STANDARD_HANGUP_LOCALUSERS; + return ast_unregister_application(app); +} + +int load_module(void) +{ + return ast_register_application(app, directory_exec); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} diff --git a/include/asterisk/say.h b/include/asterisk/say.h new file mode 100755 index 0000000000000000000000000000000000000000..357d44f9fb178014eecbd3b3b76ef0d0d02a2fba --- /dev/null +++ b/include/asterisk/say.h @@ -0,0 +1,32 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Say numbers and dates (maybe words one day too) + * + * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#ifndef _ASTERISK_SAY_H +#define _ASTERISK_SAY_H + +#include <asterisk/channel.h> +#include <asterisk/file.h> + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" { +#endif + +int ast_say_number(struct ast_channel *chan, int num); +int ast_say_digits(struct ast_channel *chan, int num); +int ast_say_digit_str(struct ast_channel *chan, char *num); + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif + +#endif diff --git a/say.c b/say.c new file mode 100755 index 0000000000000000000000000000000000000000..9ec87e7e7bae114cfbacae24931d0292cd743bd8 --- /dev/null +++ b/say.c @@ -0,0 +1,67 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Say numbers and dates (maybe words one day too) + * + * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC + * + * Mark Spencer <markster@linux-support.net> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <asterisk/file.h> +#include <asterisk/channel.h> +#include <asterisk/logger.h> +#include <asterisk/say.h> +#include <stdio.h> + +int ast_say_digit_str(struct ast_channel *chan, char *fn2) +{ + char fn[256] = ""; + int num = 0; + int res = 0; + while(fn2[num] && !res) { + snprintf(fn, sizeof(fn), "digits/%c", fn2[num]); + res = ast_streamfile(chan, fn); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + ast_stopstream(chan); + num++; + } + return res; +} + +int ast_say_digits(struct ast_channel *chan, int num) +{ + char fn2[256]; + snprintf(fn2, sizeof(fn2), "%d", num); + return ast_say_digit_str(chan, fn2); +} +int ast_say_number(struct ast_channel *chan, int num) +{ + int res = 0; + char fn[256] = ""; + while(num && !res) { + if (num < 20) { + snprintf(fn, sizeof(fn), "digits/%d", num); + num = 0; + } else + if (num < 100) { + snprintf(fn, sizeof(fn), "digits/%d", (num /10) * 10); + num -= ((num / 10) * 10); + } else { + ast_log(LOG_DEBUG, "Number '%d' is too big for me\n", num); + res = -1; + } + if (!res) { + res = ast_streamfile(chan, fn); + if (!res) + res = ast_waitstream(chan, AST_DIGIT_ANY); + ast_stopstream(chan); + } + + } + return res; +}