00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <sys/time.h>
00047 #include <sys/stat.h>
00048 #include <sys/types.h>
00049 #include <sys/mman.h>
00050 #include <time.h>
00051 #include <dirent.h>
00052
00053 #include "asterisk.h"
00054
00055 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 10464 $")
00056
00057 #include "asterisk/lock.h"
00058 #include "asterisk/file.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/channel.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/config.h"
00064 #include "asterisk/say.h"
00065 #include "asterisk/module.h"
00066 #include "asterisk/adsi.h"
00067 #include "asterisk/app.h"
00068 #include "asterisk/manager.h"
00069 #include "asterisk/dsp.h"
00070 #include "asterisk/localtime.h"
00071 #include "asterisk/cli.h"
00072 #include "asterisk/utils.h"
00073 #ifdef USE_ODBC_STORAGE
00074 #include "asterisk/res_odbc.h"
00075 #endif
00076
00077 #define COMMAND_TIMEOUT 5000
00078 #define VOICEMAIL_DIR_MODE 0700
00079 #define VOICEMAIL_FILE_MODE 0600
00080
00081 #define VOICEMAIL_CONFIG "voicemail.conf"
00082 #define ASTERISK_USERNAME "asterisk"
00083
00084
00085
00086 #define SENDMAIL "/usr/sbin/sendmail -t"
00087
00088 #define INTRO "vm-intro"
00089
00090 #define MAXMSG 100
00091 #define MAXMSGLIMIT 9999
00092
00093 #define BASEMAXINLINE 256
00094 #define BASELINELEN 72
00095 #define BASEMAXINLINE 256
00096 #define eol "\r\n"
00097
00098 #define MAX_DATETIME_FORMAT 512
00099 #define MAX_NUM_CID_CONTEXTS 10
00100
00101 #define VM_REVIEW (1 << 0)
00102 #define VM_OPERATOR (1 << 1)
00103 #define VM_SAYCID (1 << 2)
00104 #define VM_SVMAIL (1 << 3)
00105 #define VM_ENVELOPE (1 << 4)
00106 #define VM_SAYDURATION (1 << 5)
00107 #define VM_SKIPAFTERCMD (1 << 6)
00108 #define VM_FORCENAME (1 << 7)
00109 #define VM_FORCEGREET (1 << 8)
00110 #define VM_PBXSKIP (1 << 9)
00111 #define VM_DIRECFORWARD (1 << 10)
00112 #define VM_ATTACH (1 << 11)
00113 #define VM_DELETE (1 << 12)
00114 #define VM_ALLOCED (1 << 13)
00115 #define VM_SEARCH (1 << 14)
00116
00117 #define ERROR_LOCK_PATH -100
00118
00119 enum {
00120 OPT_SILENT = (1 << 0),
00121 OPT_BUSY_GREETING = (1 << 1),
00122 OPT_UNAVAIL_GREETING = (1 << 2),
00123 OPT_RECORDGAIN = (1 << 3),
00124 OPT_PREPEND_MAILBOX = (1 << 4),
00125 OPT_PRIORITY_JUMP = (1 << 5),
00126 } vm_option_flags;
00127
00128 enum {
00129 OPT_ARG_RECORDGAIN = 0,
00130 OPT_ARG_ARRAY_SIZE = 1,
00131 } vm_option_args;
00132
00133 AST_APP_OPTIONS(vm_app_options, {
00134 AST_APP_OPTION('s', OPT_SILENT),
00135 AST_APP_OPTION('b', OPT_BUSY_GREETING),
00136 AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
00137 AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
00138 AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
00139 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00140 });
00141
00142 static int load_config(void);
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 struct baseio {
00206 int iocp;
00207 int iolen;
00208 int linelength;
00209 int ateof;
00210 unsigned char iobuf[BASEMAXINLINE];
00211 };
00212
00213
00214 struct ast_vm_user {
00215 char context[AST_MAX_CONTEXT];
00216 char mailbox[AST_MAX_EXTENSION];
00217 char password[80];
00218 char fullname[80];
00219 char email[80];
00220 char pager[80];
00221 char serveremail[80];
00222 char mailcmd[160];
00223 char language[MAX_LANGUAGE];
00224 char zonetag[80];
00225 char callback[80];
00226 char dialout[80];
00227 char uniqueid[20];
00228 char exit[80];
00229 unsigned int flags;
00230 int saydurationm;
00231 int maxmsg;
00232 struct ast_vm_user *next;
00233 };
00234
00235 struct vm_zone {
00236 char name[80];
00237 char timezone[80];
00238 char msg_format[512];
00239 struct vm_zone *next;
00240 };
00241
00242 struct vm_state {
00243 char curbox[80];
00244 char username[80];
00245 char curdir[256];
00246 char vmbox[256];
00247 char fn[256];
00248 char fn2[256];
00249 int *deleted;
00250 int *heard;
00251 int curmsg;
00252 int lastmsg;
00253 int newmessages;
00254 int oldmessages;
00255 int starting;
00256 int repeats;
00257 };
00258 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg,
00259 int option, signed char record_gain);
00260 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
00261 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
00262 char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
00263 signed char record_gain);
00264 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
00265 static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
00266
00267 static void apply_options(struct ast_vm_user *vmu, const char *options);
00268
00269 #ifdef USE_ODBC_STORAGE
00270 static char odbc_database[80];
00271 static char odbc_table[80];
00272 #define RETRIEVE(a,b) retrieve_file(a,b)
00273 #define DISPOSE(a,b) remove_file(a,b)
00274 #define STORE(a,b,c,d) store_file(a,b,c,d)
00275 #define EXISTS(a,b,c,d) (message_exists(a,b))
00276 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
00277 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
00278 #define DELETE(a,b,c) (delete_file(a,b))
00279 #else
00280 #define RETRIEVE(a,b)
00281 #define DISPOSE(a,b)
00282 #define STORE(a,b,c,d)
00283 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00284 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00285 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
00286 #define DELETE(a,b,c) (vm_delete(c))
00287 #endif
00288
00289 static char VM_SPOOL_DIR[AST_CONFIG_MAX_PATH];
00290
00291 static char ext_pass_cmd[128];
00292
00293 static char *tdesc = "Comedian Mail (Voicemail System)";
00294
00295 static char *addesc = "Comedian Mail";
00296
00297 static char *synopsis_vm =
00298 "Leave a Voicemail message";
00299
00300 static char *descrip_vm =
00301 " VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
00302 "application allows the calling party to leave a message for the specified\n"
00303 "list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
00304 "be taken from the first mailbox specified. Dialplan execution will stop if the\n"
00305 "specified mailbox does not exist.\n"
00306 " The Voicemail application will exit if any of the following DTMF digits are\n"
00307 "received:\n"
00308 " 0 - Jump to the 'o' extension in the current dialplan context.\n"
00309 " * - Jump to the 'a' extension in the current dialplan context.\n"
00310 " This application will set the following channel variable upon completion:\n"
00311 " VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
00312 " application. The possible values are:\n"
00313 " SUCCESS | USEREXIT | FAILED\n\n"
00314 " Options:\n"
00315 " b - Play the 'busy' greeting to the calling party.\n"
00316 " g(#) - Use the specified amount of gain when recording the voicemail\n"
00317 " message. The units are whole-number decibels (dB).\n"
00318 " s - Skip the playback of instructions for leaving a message to the\n"
00319 " calling party.\n"
00320 " u - Play the 'unavailble greeting.\n"
00321 " j - Jump to priority n+101 if the mailbox is not found or some other\n"
00322 " error occurs.\n";
00323
00324 static char *synopsis_vmain =
00325 "Check Voicemail messages";
00326
00327 static char *descrip_vmain =
00328 " VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
00329 "calling party to check voicemail messages. A specific mailbox, and optional\n"
00330 "corresponding context, may be specified. If a mailbox is not provided, the\n"
00331 "calling party will be prompted to enter one. If a context is not specified,\n"
00332 "the 'default' context will be used.\n\n"
00333 " Options:\n"
00334 " p - Consider the mailbox parameter as a prefix to the mailbox that\n"
00335 " is entered by the caller.\n"
00336 " g(#) - Use the specified amount of gain when recording a voicemail\n"
00337 " message. The units are whole-number decibels (dB).\n"
00338 " s - Skip checking the passcode for the mailbox.\n";
00339
00340 static char *synopsis_vm_box_exists =
00341 "Check to see if Voicemail mailbox exists";
00342
00343 static char *descrip_vm_box_exists =
00344 " MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
00345 "mailbox exists. If no voicemail context is specified, the 'default' context\n"
00346 "will be used.\n"
00347 " This application will set the following channel variable upon completion:\n"
00348 " VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
00349 " MailboxExists application. Possible values include:\n"
00350 " SUCCESS | FAILED\n\n"
00351 " Options:\n"
00352 " j - Jump to priority n+101 if the mailbox is found.\n";
00353
00354 static char *synopsis_vmauthenticate =
00355 "Authenticate with Voicemail passwords";
00356
00357 static char *descrip_vmauthenticate =
00358 " VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
00359 "same way as the Authenticate application, but the passwords are taken from\n"
00360 "voicemail.conf.\n"
00361 " If the mailbox is specified, only that mailbox's password will be considered\n"
00362 "valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
00363 "be set with the authenticated mailbox.\n\n"
00364 " Options:\n"
00365 " s - Skip playing the initial prompts.\n";
00366
00367
00368 static char *app = "VoiceMail";
00369
00370
00371 static char *app2 = "VoiceMailMain";
00372
00373 static char *app3 = "MailboxExists";
00374 static char *app4 = "VMAuthenticate";
00375
00376 AST_MUTEX_DEFINE_STATIC(vmlock);
00377 struct ast_vm_user *users;
00378 struct ast_vm_user *usersl;
00379 struct vm_zone *zones = NULL;
00380 struct vm_zone *zonesl = NULL;
00381 static int maxsilence;
00382 static int maxmsg;
00383 static int silencethreshold = 128;
00384 static char serveremail[80];
00385 static char mailcmd[160];
00386 static char externnotify[160];
00387
00388 static char vmfmts[80];
00389 static int vmminmessage;
00390 static int vmmaxmessage;
00391 static int maxgreet;
00392 static int skipms;
00393 static int maxlogins;
00394
00395 static struct ast_flags globalflags = {0};
00396
00397 static int saydurationminfo;
00398
00399 static char dialcontext[AST_MAX_CONTEXT];
00400 static char callcontext[AST_MAX_CONTEXT];
00401 static char exitcontext[AST_MAX_CONTEXT];
00402
00403 static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
00404
00405
00406 static char *emailbody = NULL;
00407 static char *emailsubject = NULL;
00408 static char *pagerbody = NULL;
00409 static char *pagersubject = NULL;
00410 static char fromstring[100];
00411 static char pagerfromstring[100];
00412 static char emailtitle[100];
00413 static char charset[32] = "ISO-8859-1";
00414
00415 static unsigned char adsifdn[4] = "\x00\x00\x00\x0F";
00416 static unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC";
00417 static int adsiver = 1;
00418 static char emaildateformat[32] = "%A, %B %d, %Y at %r";
00419
00420 STANDARD_LOCAL_USER;
00421
00422 LOCAL_USER_DECL;
00423
00424 static void populate_defaults(struct ast_vm_user *vmu)
00425 {
00426 ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
00427 if (saydurationminfo)
00428 vmu->saydurationm = saydurationminfo;
00429 if (callcontext)
00430 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00431 if (dialcontext)
00432 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00433 if (exitcontext)
00434 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00435 if (maxmsg)
00436 vmu->maxmsg = maxmsg;
00437 }
00438
00439 static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
00440 {
00441 int x;
00442 if (!strcasecmp(var, "attach")) {
00443 ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00444 } else if (!strcasecmp(var, "serveremail")) {
00445 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00446 } else if (!strcasecmp(var, "language")) {
00447 ast_copy_string(vmu->language, value, sizeof(vmu->language));
00448 } else if (!strcasecmp(var, "tz")) {
00449 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00450 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00451 ast_set2_flag(vmu, ast_true(value), VM_DELETE);
00452 } else if (!strcasecmp(var, "saycid")){
00453 ast_set2_flag(vmu, ast_true(value), VM_SAYCID);
00454 } else if (!strcasecmp(var,"sendvoicemail")){
00455 ast_set2_flag(vmu, ast_true(value), VM_SVMAIL);
00456 } else if (!strcasecmp(var, "review")){
00457 ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00458 } else if (!strcasecmp(var, "operator")){
00459 ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);
00460 } else if (!strcasecmp(var, "envelope")){
00461 ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);
00462 } else if (!strcasecmp(var, "sayduration")){
00463 ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);
00464 } else if (!strcasecmp(var, "saydurationm")){
00465 if (sscanf(value, "%d", &x) == 1) {
00466 vmu->saydurationm = x;
00467 } else {
00468 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
00469 }
00470 } else if (!strcasecmp(var, "forcename")){
00471 ast_set2_flag(vmu, ast_true(value), VM_FORCENAME);
00472 } else if (!strcasecmp(var, "forcegreetings")){
00473 ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);
00474 } else if (!strcasecmp(var, "callback")) {
00475 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00476 } else if (!strcasecmp(var, "dialout")) {
00477 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00478 } else if (!strcasecmp(var, "exitcontext")) {
00479 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00480 } else if (!strcasecmp(var, "maxmsg")) {
00481 vmu->maxmsg = atoi(value);
00482 if (vmu->maxmsg <= 0) {
00483 ast_log(LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %i\n", value, MAXMSG);
00484 vmu->maxmsg = MAXMSG;
00485 } else if (vmu->maxmsg > MAXMSGLIMIT) {
00486 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00487 vmu->maxmsg = MAXMSGLIMIT;
00488 }
00489 } else if (!strcasecmp(var, "options")) {
00490 apply_options(vmu, value);
00491 }
00492 }
00493
00494 static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
00495 {
00496 int res;
00497 if (!ast_strlen_zero(vmu->uniqueid)) {
00498 res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, NULL);
00499 if (res > 0) {
00500 ast_copy_string(vmu->password, password, sizeof(vmu->password));
00501 res = 0;
00502 } else if (!res) {
00503 res = -1;
00504 }
00505 return res;
00506 }
00507 return -1;
00508 }
00509
00510 static void apply_options(struct ast_vm_user *vmu, const char *options)
00511 {
00512 char *stringp;
00513 char *s;
00514 char *var, *value;
00515 stringp = ast_strdupa(options);
00516 while ((s = strsep(&stringp, "|"))) {
00517 value = s;
00518 if ((var = strsep(&value, "=")) && value) {
00519 apply_option(vmu, var, value);
00520 }
00521 }
00522 }
00523
00524 static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00525 {
00526 struct ast_variable *var, *tmp;
00527 struct ast_vm_user *retval;
00528
00529 if (ivm)
00530 retval=ivm;
00531 else
00532 retval=malloc(sizeof(struct ast_vm_user));
00533
00534 if (retval) {
00535 memset(retval, 0, sizeof(struct ast_vm_user));
00536 if (!ivm)
00537 ast_set_flag(retval, VM_ALLOCED);
00538 if (mailbox)
00539 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
00540 populate_defaults(retval);
00541 if (!context && ast_test_flag((&globalflags), VM_SEARCH))
00542 var = ast_load_realtime("voicemail", "mailbox", mailbox, NULL);
00543 else
00544 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
00545 if (var) {
00546 tmp = var;
00547 while(tmp) {
00548 printf("%s => %s\n", tmp->name, tmp->value);
00549 if (!strcasecmp(tmp->name, "password")) {
00550 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00551 } else if (!strcasecmp(tmp->name, "uniqueid")) {
00552 ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00553 } else if (!strcasecmp(tmp->name, "pager")) {
00554 ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
00555 } else if (!strcasecmp(tmp->name, "email")) {
00556 ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
00557 } else if (!strcasecmp(tmp->name, "fullname")) {
00558 ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
00559 } else if (!strcasecmp(tmp->name, "context")) {
00560 ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
00561 } else
00562 apply_option(retval, tmp->name, tmp->value);
00563 tmp = tmp->next;
00564 }
00565 } else {
00566 if (!ivm)
00567 free(retval);
00568 retval = NULL;
00569 }
00570 }
00571 return retval;
00572 }
00573
00574 static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00575 {
00576
00577 struct ast_vm_user *vmu=NULL, *cur;
00578 ast_mutex_lock(&vmlock);
00579 cur = users;
00580
00581 if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
00582 context = "default";
00583
00584 while (cur) {
00585 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
00586 break;
00587 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
00588 break;
00589 cur=cur->next;
00590 }
00591 if (cur) {
00592 if (ivm)
00593 vmu = ivm;
00594 else
00595
00596 vmu = malloc(sizeof(struct ast_vm_user));
00597 if (vmu) {
00598 memcpy(vmu, cur, sizeof(struct ast_vm_user));
00599 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
00600 vmu->next = NULL;
00601 }
00602 } else
00603 vmu = find_user_realtime(ivm, context, mailbox);
00604 ast_mutex_unlock(&vmlock);
00605 return vmu;
00606 }
00607
00608 static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
00609 {
00610
00611 struct ast_vm_user *cur;
00612 int res = -1;
00613 ast_mutex_lock(&vmlock);
00614 cur = users;
00615 while (cur) {
00616 if ((!context || !strcasecmp(context, cur->context)) &&
00617 (!strcasecmp(mailbox, cur->mailbox)))
00618 break;
00619 cur=cur->next;
00620 }
00621 if (cur) {
00622 ast_copy_string(cur->password, newpass, sizeof(cur->password));
00623 res = 0;
00624 }
00625 ast_mutex_unlock(&vmlock);
00626 return res;
00627 }
00628
00629 static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
00630 {
00631
00632
00633
00634
00635 FILE *configin;
00636 FILE *configout;
00637 int linenum=0;
00638 char inbuf[256];
00639 char orig[256];
00640 char currcontext[256] ="";
00641 char tmpin[AST_CONFIG_MAX_PATH];
00642 char tmpout[AST_CONFIG_MAX_PATH];
00643 struct stat statbuf;
00644
00645 if (!change_password_realtime(vmu, newpassword))
00646 return;
00647
00648 snprintf(tmpin, sizeof(tmpin), "%s/voicemail.conf", ast_config_AST_CONFIG_DIR);
00649 snprintf(tmpout, sizeof(tmpout), "%s/voicemail.conf.new", ast_config_AST_CONFIG_DIR);
00650 configin = fopen(tmpin,"r");
00651 if (configin)
00652 configout = fopen(tmpout,"w+");
00653 else
00654 configout = NULL;
00655 if (!configin || !configout) {
00656 if (configin)
00657 fclose(configin);
00658 else
00659 ast_log(LOG_WARNING, "Warning: Unable to open '%s' for reading: %s\n", tmpin, strerror(errno));
00660 if (configout)
00661 fclose(configout);
00662 else
00663 ast_log(LOG_WARNING, "Warning: Unable to open '%s' for writing: %s\n", tmpout, strerror(errno));
00664 return;
00665 }
00666
00667 while (!feof(configin)) {
00668 char *user = NULL, *pass = NULL, *rest = NULL, *comment = NULL, *tmpctx = NULL, *tmpctxend = NULL;
00669
00670
00671 fgets(inbuf, sizeof(inbuf), configin);
00672 linenum++;
00673
00674 if (ast_strlen_zero(inbuf)) {
00675 fprintf(configout, "\n");
00676 continue;
00677 }
00678
00679
00680 ast_copy_string(orig, inbuf, sizeof(orig));
00681
00682
00683
00684
00685
00686 if (inbuf[strlen(inbuf) - 1] == '\n')
00687 inbuf[strlen(inbuf) - 1] = '\0';
00688
00689 if ((comment = strchr(inbuf, ';')))
00690 *comment++ = '\0';
00691
00692 if (ast_strlen_zero(inbuf)) {
00693 fprintf(configout, "%s", orig);
00694 continue;
00695 }
00696
00697
00698 if ((tmpctx = strchr(inbuf, '['))) {
00699 tmpctxend = strchr(tmpctx, ']');
00700 if (tmpctxend) {
00701
00702 ast_copy_string(currcontext, tmpctx + 1, tmpctxend - tmpctx);
00703 fprintf(configout, "%s", orig);
00704 continue;
00705 }
00706 }
00707
00708
00709 user = inbuf;
00710 if ((pass = strchr(user, '='))) {
00711
00712 *pass++ = '\0';
00713
00714 user = ast_strip(user);
00715
00716 if (*pass == '>')
00717 *pass++ = '\0';
00718
00719 pass = ast_skip_blanks(pass);
00720
00721
00722
00723
00724
00725
00726 if ((rest = strchr(pass, ',')))
00727 *rest++ = '\0';
00728 } else {
00729 user = NULL;
00730 }
00731
00732
00733 if (!ast_strlen_zero(user) && !strcmp(user, vmu->mailbox) &&
00734 !ast_strlen_zero(pass) && !strcmp(pass, vmu->password) &&
00735 !strcasecmp(currcontext, vmu->context)) {
00736
00737 if (rest) {
00738 fprintf(configout, "%s => %s,%s", user, newpassword, rest);
00739 } else {
00740 fprintf(configout, "%s => %s", user, newpassword);
00741 }
00742
00743 if (comment) {
00744 fprintf(configout, ";%s\n", comment);
00745 } else {
00746 fprintf(configout, "\n");
00747 }
00748 } else {
00749
00750 fprintf(configout, "%s", orig);
00751 }
00752 }
00753 fclose(configin);
00754 fclose(configout);
00755
00756 stat(tmpin, &statbuf);
00757 chmod(tmpout, statbuf.st_mode);
00758 chown(tmpout, statbuf.st_uid, statbuf.st_gid);
00759 unlink(tmpin);
00760 rename(tmpout, tmpin);
00761 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
00762 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00763 }
00764
00765 static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
00766 {
00767 char buf[255];
00768 snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
00769 if (!ast_safe_system(buf))
00770 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00771 }
00772
00773 static int make_dir(char *dest, int len, char *context, char *ext, char *mailbox)
00774 {
00775 return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, mailbox);
00776 }
00777
00778 static int make_file(char *dest, int len, char *dir, int num)
00779 {
00780 return snprintf(dest, len, "%s/msg%04d", dir, num);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790 static int create_dirpath(char *dest, int len, char *context, char *ext, char *mailbox)
00791 {
00792 mode_t mode = VOICEMAIL_DIR_MODE;
00793
00794 if(context && context[0] != '\0') {
00795 make_dir(dest, len, context, "", "");
00796 if(mkdir(dest, mode) && errno != EEXIST) {
00797 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00798 return 0;
00799 }
00800 }
00801 if(ext && ext[0] != '\0') {
00802 make_dir(dest, len, context, ext, "");
00803 if(mkdir(dest, mode) && errno != EEXIST) {
00804 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00805 return 0;
00806 }
00807 }
00808 if(mailbox && mailbox[0] != '\0') {
00809 make_dir(dest, len, context, ext, mailbox);
00810 if(mkdir(dest, mode) && errno != EEXIST) {
00811 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00812 return 0;
00813 }
00814 }
00815 return 1;
00816 }
00817
00818
00819
00820
00821 static int vm_lock_path(const char *path)
00822 {
00823 switch (ast_lock_path(path)) {
00824 case AST_LOCK_TIMEOUT:
00825 return -1;
00826 default:
00827 return 0;
00828 }
00829 }
00830
00831
00832 #ifdef USE_ODBC_STORAGE
00833 static int retrieve_file(char *dir, int msgnum)
00834 {
00835 int x = 0;
00836 int res;
00837 int fd=-1;
00838 size_t fdlen = 0;
00839 void *fdm=NULL;
00840 SQLSMALLINT colcount=0;
00841 SQLHSTMT stmt;
00842 char sql[256];
00843 char fmt[80]="";
00844 char *c;
00845 char coltitle[256];
00846 SQLSMALLINT collen;
00847 SQLSMALLINT datatype;
00848 SQLSMALLINT decimaldigits;
00849 SQLSMALLINT nullable;
00850 SQLULEN colsize;
00851 FILE *f=NULL;
00852 char rowdata[80];
00853 char fn[256];
00854 char full_fn[256];
00855 char msgnums[80];
00856
00857 odbc_obj *obj;
00858 obj = fetch_odbc_obj(odbc_database, 0);
00859 if (obj) {
00860 ast_copy_string(fmt, vmfmts, sizeof(fmt));
00861 c = strchr(fmt, '|');
00862 if (c)
00863 *c = '\0';
00864 if (!strcasecmp(fmt, "wav49"))
00865 strcpy(fmt, "WAV");
00866 snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
00867 if (msgnum > -1)
00868 make_file(fn, sizeof(fn), dir, msgnum);
00869 else
00870 ast_copy_string(fn, dir, sizeof(fn));
00871 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
00872 f = fopen(full_fn, "w+");
00873 snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
00874 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00875 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00876 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00877 goto yuck;
00878 }
00879 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table);
00880 res = SQLPrepare(stmt, sql, SQL_NTS);
00881 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00882 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00883 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00884 goto yuck;
00885 }
00886 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
00887 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
00888 res = odbc_smart_execute(obj, stmt);
00889 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00890 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
00891 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00892 goto yuck;
00893 }
00894 res = SQLFetch(stmt);
00895 if (res == SQL_NO_DATA) {
00896 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00897 goto yuck;
00898 }
00899 else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00900 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00901 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00902 goto yuck;
00903 }
00904 fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC);
00905 if (fd < 0) {
00906 ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
00907 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00908 goto yuck;
00909 }
00910 res = SQLNumResultCols(stmt, &colcount);
00911 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00912 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00913 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00914 goto yuck;
00915 }
00916 if (f)
00917 fprintf(f, "[message]\n");
00918 for (x=0;x<colcount;x++) {
00919 rowdata[0] = '\0';
00920 collen = sizeof(coltitle);
00921 res = SQLDescribeCol(stmt, x + 1, coltitle, sizeof(coltitle), &collen,
00922 &datatype, &colsize, &decimaldigits, &nullable);
00923 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00924 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00925 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00926 goto yuck;
00927 }
00928 if (!strcasecmp(coltitle, "recording")) {
00929 res = SQLGetData(stmt, x + 1, SQL_BINARY, NULL, 0, &colsize);
00930 fdlen = colsize;
00931 fd = open(full_fn, O_RDWR | O_TRUNC | O_CREAT, 0770);
00932 if (fd > -1) {
00933 char tmp[1]="";
00934 lseek(fd, fdlen - 1, SEEK_SET);
00935 if (write(fd, tmp, 1) != 1) {
00936 close(fd);
00937 fd = -1;
00938 }
00939 if (fd > -1)
00940 fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
00941 }
00942 if (fdm) {
00943 memset(fdm, 0, fdlen);
00944 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, fdlen, &colsize);
00945 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00946 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00947 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00948 goto yuck;
00949 }
00950 }
00951 } else {
00952 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
00953 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00954 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00955 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00956 goto yuck;
00957 }
00958 if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
00959 fprintf(f, "%s=%s\n", coltitle, rowdata);
00960 }
00961 }
00962 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00963 } else
00964 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
00965 yuck:
00966 if (f)
00967 fclose(f);
00968 if (fdm)
00969 munmap(fdm, fdlen);
00970 if (fd > -1)
00971 close(fd);
00972 return x - 1;
00973 }
00974
00975 static int remove_file(char *dir, int msgnum)
00976 {
00977 char fn[256];
00978 char full_fn[256];
00979 char msgnums[80];
00980
00981 if (msgnum > -1) {
00982 snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
00983 make_file(fn, sizeof(fn), dir, msgnum);
00984 } else
00985 ast_copy_string(fn, dir, sizeof(fn));
00986 ast_filedelete(fn, NULL);
00987 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
00988 unlink(full_fn);
00989 return 0;
00990 }
00991
00992 static int last_message_index(struct ast_vm_user *vmu, char *dir)
00993 {
00994 int x = 0;
00995 int res;
00996 SQLHSTMT stmt;
00997 char sql[256];
00998 char rowdata[20];
00999
01000 odbc_obj *obj;
01001 obj = fetch_odbc_obj(odbc_database, 0);
01002 if (obj) {
01003 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01004 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01005 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01006 goto yuck;
01007 }
01008 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?",odbc_table);
01009 res = SQLPrepare(stmt, sql, SQL_NTS);
01010 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01011 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01012 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01013 goto yuck;
01014 }
01015 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
01016 res = odbc_smart_execute(obj, stmt);
01017 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01018 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01019 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01020 goto yuck;
01021 }
01022 res = SQLFetch(stmt);
01023 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01024 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
01025 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01026 goto yuck;
01027 }
01028 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
01029 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01030 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01031 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01032 goto yuck;
01033 }
01034 if (sscanf(rowdata, "%d", &x) != 1)
01035 ast_log(LOG_WARNING, "Failed to read message count!\n");
01036 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01037 } else
01038 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01039 yuck:
01040 return x - 1;
01041 }
01042
01043 static int message_exists(char *dir, int msgnum)
01044 {
01045 int x = 0;
01046 int res;
01047 SQLHSTMT stmt;
01048 char sql[256];
01049 char rowdata[20];
01050 char msgnums[20];
01051
01052 odbc_obj *obj;
01053 obj = fetch_odbc_obj(odbc_database, 0);
01054 if (obj) {
01055 snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
01056 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01057 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01058 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01059 goto yuck;
01060 }
01061 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?",odbc_table);
01062 res = SQLPrepare(stmt, sql, SQL_NTS);
01063 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01064 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01065 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01066 goto yuck;
01067 }
01068 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
01069 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01070 res = odbc_smart_execute(obj, stmt);
01071 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01072 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01073 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01074 goto yuck;
01075 }
01076 res = SQLFetch(stmt);
01077 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01078 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
01079 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01080 goto yuck;
01081 }
01082 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
01083 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01084 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01085 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01086 goto yuck;
01087 }
01088 if (sscanf(rowdata, "%d", &x) != 1)
01089 ast_log(LOG_WARNING, "Failed to read message count!\n");
01090 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01091 } else
01092 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01093 yuck:
01094 return x;
01095 }
01096
01097 static int count_messages(struct ast_vm_user *vmu, char *dir)
01098 {
01099 return last_message_index(vmu, dir) + 1;
01100 }
01101
01102 static void delete_file(char *sdir, int smsg)
01103 {
01104 int res;
01105 SQLHSTMT stmt;
01106 char sql[256];
01107 char msgnums[20];
01108
01109 odbc_obj *obj;
01110 obj = fetch_odbc_obj(odbc_database, 0);
01111 if (obj) {
01112 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01113 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01114 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01115 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01116 goto yuck;
01117 }
01118 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?",odbc_table);
01119 res = SQLPrepare(stmt, sql, SQL_NTS);
01120 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01121 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01122 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01123 goto yuck;
01124 }
01125 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
01126 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01127 res = odbc_smart_execute(obj, stmt);
01128 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01129 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01130 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01131 goto yuck;
01132 }
01133 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01134 } else
01135 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01136 yuck:
01137 return;
01138 }
01139
01140 static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext)
01141 {
01142 int res;
01143 SQLHSTMT stmt;
01144 char sql[512];
01145 char msgnums[20];
01146 char msgnumd[20];
01147 odbc_obj *obj;
01148
01149 delete_file(ddir, dmsg);
01150 obj = fetch_odbc_obj(odbc_database, 0);
01151 if (obj) {
01152 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01153 snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
01154 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01155 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01156 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01157 goto yuck;
01158 }
01159 #ifdef EXTENDED_ODBC_STORAGE
01160 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording, mailboxuser, mailboxcontext) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording,?,? FROM %s WHERE dir=? AND msgnum=?",odbc_table,odbc_table);
01161 #else
01162 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, context, macrocontext, callerid, origtime, duration, recording) SELECT ?,?,context,macrocontext,callerid,origtime,duration,recording FROM %s WHERE dir=? AND msgnum=?",odbc_table,odbc_table);
01163 #endif
01164 res = SQLPrepare(stmt, sql, SQL_NTS);
01165 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01166 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01167 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01168 goto yuck;
01169 }
01170 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL);
01171 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL);
01172 #ifdef EXTENDED_ODBC_STORAGE
01173 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxuser), 0, (void *)dmailboxuser, 0, NULL);
01174 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dmailboxcontext), 0, (void *)dmailboxcontext, 0, NULL);
01175 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
01176 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01177 #else
01178 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
01179 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01180 #endif
01181 res = odbc_smart_execute(obj, stmt);
01182 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01183 ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
01184 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01185 goto yuck;
01186 }
01187 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01188 } else
01189 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01190 yuck:
01191 return;
01192 }
01193
01194 static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum)
01195 {
01196 int x = 0;
01197 int res;
01198 int fd = -1;
01199 void *fdm=NULL;
01200 size_t fdlen = -1;
01201 SQLHSTMT stmt;
01202 SQLINTEGER len;
01203 char sql[256];
01204 char msgnums[20];
01205 char fn[256];
01206 char full_fn[256];
01207 char fmt[80]="";
01208 char *c;
01209 char *context="", *macrocontext="", *callerid="", *origtime="", *duration="";
01210 char *category = "";
01211 struct ast_config *cfg=NULL;
01212 odbc_obj *obj;
01213
01214 delete_file(dir, msgnum);
01215 obj = fetch_odbc_obj(odbc_database, 0);
01216 if (obj) {
01217 ast_copy_string(fmt, vmfmts, sizeof(fmt));
01218 c = strchr(fmt, '|');
01219 if (c)
01220 *c = '\0';
01221 if (!strcasecmp(fmt, "wav49"))
01222 strcpy(fmt, "WAV");
01223 snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
01224 if (msgnum > -1)
01225 make_file(fn, sizeof(fn), dir, msgnum);
01226 else
01227 ast_copy_string(fn, dir, sizeof(fn));
01228 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
01229 cfg = ast_config_load(full_fn);
01230 snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
01231 fd = open(full_fn, O_RDWR);
01232 if (fd < 0) {
01233 ast_log(LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno));
01234 goto yuck;
01235 }
01236 if (cfg) {
01237 context = ast_variable_retrieve(cfg, "message", "context");
01238 if (!context) context = "";
01239 macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext");
01240 if (!macrocontext) macrocontext = "";
01241 callerid = ast_variable_retrieve(cfg, "message", "callerid");
01242 if (!callerid) callerid = "";
01243 origtime = ast_variable_retrieve(cfg, "message", "origtime");
01244 if (!origtime) origtime = "";
01245 duration = ast_variable_retrieve(cfg, "message", "duration");
01246 if (!duration) duration = "";
01247 category = ast_variable_retrieve(cfg, "message", "category");
01248 if (!category) category = "";
01249 }
01250 fdlen = lseek(fd, 0, SEEK_END);
01251 lseek(fd, 0, SEEK_SET);
01252 printf("Length is %d\n", fdlen);
01253 fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
01254 if (!fdm) {
01255 ast_log(LOG_WARNING, "Memory map failed!\n");
01256 goto yuck;
01257 }
01258 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01259 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01260 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01261 goto yuck;
01262 }
01263 if (!ast_strlen_zero(category))
01264 #ifdef EXTENDED_ODBC_STORAGE
01265 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)",odbc_table);
01266 #else
01267 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,category) VALUES (?,?,?,?,?,?,?,?,?)",odbc_table);
01268 #endif
01269 else
01270 #ifdef EXTENDED_ODBC_STORAGE
01271 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext) VALUES (?,?,?,?,?,?,?,?,?,?)",odbc_table);
01272 #else
01273 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration) VALUES (?,?,?,?,?,?,?,?)",odbc_table);
01274 #endif
01275 res = SQLPrepare(stmt, sql, SQL_NTS);
01276 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01277 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01278 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01279 goto yuck;
01280 }
01281 len = fdlen;
01282 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
01283 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01284 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_BINARY, fdlen, 0, (void *)fdm, fdlen, &len);
01285 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(context), 0, (void *)context, 0, NULL);
01286 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(macrocontext), 0, (void *)macrocontext, 0, NULL);
01287 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(callerid), 0, (void *)callerid, 0, NULL);
01288 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(origtime), 0, (void *)origtime, 0, NULL);
01289 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(duration), 0, (void *)duration, 0, NULL);
01290 #ifdef EXTENDED_ODBC_STORAGE
01291 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL);
01292 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL);
01293 if (!ast_strlen_zero(category))
01294 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL);
01295 #else
01296 if (!ast_strlen_zero(category))
01297 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL);
01298 #endif
01299 res = odbc_smart_execute(obj, stmt);
01300 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01301 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01302 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01303 goto yuck;
01304 }
01305 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01306 } else
01307 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01308 yuck:
01309 if (cfg)
01310 ast_config_destroy(cfg);
01311 if (fdm)
01312 munmap(fdm, fdlen);
01313 if (fd > -1)
01314 close(fd);
01315 return x;
01316 }
01317
01318 static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg)
01319 {
01320 int res;
01321 SQLHSTMT stmt;
01322 char sql[256];
01323 char msgnums[20];
01324 char msgnumd[20];
01325 odbc_obj *obj;
01326
01327 delete_file(ddir, dmsg);
01328 obj = fetch_odbc_obj(odbc_database, 0);
01329 if (obj) {
01330 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01331 snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
01332 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01333 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01334 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01335 goto yuck;
01336 }
01337 #ifdef EXTENDED_ODBC_STORAGE
01338 snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?",odbc_table);
01339 #else
01340 snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=? WHERE dir=? AND msgnum=?",odbc_table);
01341 #endif
01342 res = SQLPrepare(stmt, sql, SQL_NTS);
01343 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01344 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01345 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01346 goto yuck;
01347 }
01348 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(ddir), 0, (void *)ddir, 0, NULL);
01349 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnumd), 0, (void *)msgnumd, 0, NULL);
01350 #ifdef EXTENDED_ODBC_STORAGE
01351 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL);
01352 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL);
01353 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
01354 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01355 #else
01356 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(sdir), 0, (void *)sdir, 0, NULL);
01357 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01358 #endif
01359 res = odbc_smart_execute(obj, stmt);
01360 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01361 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01362 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01363 goto yuck;
01364 }
01365 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01366 } else
01367 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01368 yuck:
01369 return;
01370 }
01371
01372 #else
01373
01374 static int count_messages(struct ast_vm_user *vmu, char *dir)
01375 {
01376
01377
01378 int vmcount = 0;
01379 DIR *vmdir = NULL;
01380 struct dirent *vment = NULL;
01381
01382 if (vm_lock_path(dir))
01383 return ERROR_LOCK_PATH;
01384
01385 if ((vmdir = opendir(dir))) {
01386 while ((vment = readdir(vmdir))) {
01387 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4))
01388 vmcount++;
01389 }
01390 closedir(vmdir);
01391 }
01392 ast_unlock_path(dir);
01393
01394 return vmcount;
01395 }
01396
01397 static void rename_file(char *sfn, char *dfn)
01398 {
01399 char stxt[256];
01400 char dtxt[256];
01401 ast_filerename(sfn,dfn,NULL);
01402 snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
01403 snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
01404 rename(stxt, dtxt);
01405 }
01406
01407 static int copy(char *infile, char *outfile)
01408 {
01409 int ifd;
01410 int ofd;
01411 int res;
01412 int len;
01413 char buf[4096];
01414
01415 #ifdef HARDLINK_WHEN_POSSIBLE
01416
01417 if (link(infile, outfile)) {
01418 #endif
01419 if ((ifd = open(infile, O_RDONLY)) < 0) {
01420 ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
01421 return -1;
01422 }
01423 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
01424 ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
01425 close(ifd);
01426 return -1;
01427 }
01428 do {
01429 len = read(ifd, buf, sizeof(buf));
01430 if (len < 0) {
01431 ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
01432 close(ifd);
01433 close(ofd);
01434 unlink(outfile);
01435 }
01436 if (len) {
01437 res = write(ofd, buf, len);
01438 if (errno == ENOMEM || errno == ENOSPC || res != len) {
01439 ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
01440 close(ifd);
01441 close(ofd);
01442 unlink(outfile);
01443 }
01444 }
01445 } while (len);
01446 close(ifd);
01447 close(ofd);
01448 return 0;
01449 #ifdef HARDLINK_WHEN_POSSIBLE
01450 } else {
01451
01452 return 0;
01453 }
01454 #endif
01455 }
01456
01457 static void copy_file(char *frompath, char *topath)
01458 {
01459 char frompath2[256],topath2[256];
01460 ast_filecopy(frompath, topath, NULL);
01461 snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
01462 snprintf(topath2, sizeof(topath2), "%s.txt", topath);
01463 copy(frompath2, topath2);
01464 }
01465
01466
01467
01468
01469 static int last_message_index(struct ast_vm_user *vmu, char *dir)
01470 {
01471 int x;
01472 char fn[256];
01473
01474 if (vm_lock_path(dir))
01475 return ERROR_LOCK_PATH;
01476
01477 for (x = 0; x < vmu->maxmsg; x++) {
01478 make_file(fn, sizeof(fn), dir, x);
01479 if (ast_fileexists(fn, NULL, NULL) < 1)
01480 break;
01481 }
01482 ast_unlock_path(dir);
01483
01484 return x - 1;
01485 }
01486
01487 static int vm_delete(char *file)
01488 {
01489 char *txt;
01490 int txtsize = 0;
01491
01492 txtsize = (strlen(file) + 5)*sizeof(char);
01493 txt = (char *)alloca(txtsize);
01494
01495
01496
01497 snprintf(txt, txtsize, "%s.txt", file);
01498 unlink(txt);
01499 return ast_filedelete(file, NULL);
01500 }
01501
01502
01503 #endif
01504 static int
01505 inbuf(struct baseio *bio, FILE *fi)
01506 {
01507 int l;
01508
01509 if (bio->ateof)
01510 return 0;
01511
01512 if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
01513 if (ferror(fi))
01514 return -1;
01515
01516 bio->ateof = 1;
01517 return 0;
01518 }
01519
01520 bio->iolen= l;
01521 bio->iocp= 0;
01522
01523 return 1;
01524 }
01525
01526 static int
01527 inchar(struct baseio *bio, FILE *fi)
01528 {
01529 if (bio->iocp>=bio->iolen) {
01530 if (!inbuf(bio, fi))
01531 return EOF;
01532 }
01533
01534 return bio->iobuf[bio->iocp++];
01535 }
01536
01537 static int
01538 ochar(struct baseio *bio, int c, FILE *so)
01539 {
01540 if (bio->linelength>=BASELINELEN) {
01541 if (fputs(eol,so)==EOF)
01542 return -1;
01543
01544 bio->linelength= 0;
01545 }
01546
01547 if (putc(((unsigned char)c),so)==EOF)
01548 return -1;
01549
01550 bio->linelength++;
01551
01552 return 1;
01553 }
01554
01555 static int base_encode(char *filename, FILE *so)
01556 {
01557 unsigned char dtable[BASEMAXINLINE];
01558 int i,hiteof= 0;
01559 FILE *fi;
01560 struct baseio bio;
01561
01562 memset(&bio, 0, sizeof(bio));
01563 bio.iocp = BASEMAXINLINE;
01564
01565 if (!(fi = fopen(filename, "rb"))) {
01566 ast_log(LOG_WARNING, "Failed to open log file: %s: %s\n", filename, strerror(errno));
01567 return -1;
01568 }
01569
01570 for (i= 0;i<9;i++) {
01571 dtable[i]= 'A'+i;
01572 dtable[i+9]= 'J'+i;
01573 dtable[26+i]= 'a'+i;
01574 dtable[26+i+9]= 'j'+i;
01575 }
01576 for (i= 0;i<8;i++) {
01577 dtable[i+18]= 'S'+i;
01578 dtable[26+i+18]= 's'+i;
01579 }
01580 for (i= 0;i<10;i++) {
01581 dtable[52+i]= '0'+i;
01582 }
01583 dtable[62]= '+';
01584 dtable[63]= '/';
01585
01586 while (!hiteof){
01587 unsigned char igroup[3],ogroup[4];
01588 int c,n;
01589
01590 igroup[0]= igroup[1]= igroup[2]= 0;
01591
01592 for (n= 0;n<3;n++) {
01593 if ((c = inchar(&bio, fi)) == EOF) {
01594 hiteof= 1;
01595 break;
01596 }
01597
01598 igroup[n]= (unsigned char)c;
01599 }
01600
01601 if (n> 0) {
01602 ogroup[0]= dtable[igroup[0]>>2];
01603 ogroup[1]= dtable[((igroup[0]&3)<<4)|(igroup[1]>>4)];
01604 ogroup[2]= dtable[((igroup[1]&0xF)<<2)|(igroup[2]>>6)];
01605 ogroup[3]= dtable[igroup[2]&0x3F];
01606
01607 if (n<3) {
01608 ogroup[3]= '=';
01609
01610 if (n<2)
01611 ogroup[2]= '=';
01612 }
01613
01614 for (i= 0;i<4;i++)
01615 ochar(&bio, ogroup[i], so);
01616 }
01617 }
01618
01619 if (fputs(eol,so)==EOF)
01620 return 0;
01621
01622 fclose(fi);
01623
01624 return 1;
01625 }
01626
01627 static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *dur, char *date, char *passdata, size_t passdatasize)
01628 {
01629 char callerid[256];
01630
01631 pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
01632 pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
01633 snprintf(passdata, passdatasize, "%d", msgnum);
01634 pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
01635 pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
01636 pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
01637 pbx_builtin_setvar_helper(ast, "VM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
01638 pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (cidname ? cidname : "an unknown caller"));
01639 pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
01640 pbx_builtin_setvar_helper(ast, "VM_DATE", date);
01641 }
01642
01643 static int sendmail(char *srcemail, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, char *attach, char *format, int duration, int attach_user_voicemail)
01644 {
01645 FILE *p=NULL;
01646 int pfd;
01647 char date[256];
01648 char host[MAXHOSTNAMELEN] = "";
01649 char who[256];
01650 char bound[256];
01651 char fname[256];
01652 char dur[256];
01653 char tmp[80] = "/tmp/astmail-XXXXXX";
01654 char tmp2[256];
01655 time_t t;
01656 struct tm tm;
01657 struct vm_zone *the_zone = NULL;
01658 if (vmu && ast_strlen_zero(vmu->email)) {
01659 ast_log(LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
01660 return(0);
01661 }
01662 if (!strcmp(format, "wav49"))
01663 format = "WAV";
01664 ast_log(LOG_DEBUG, "Attaching file '%s', format '%s', uservm is '%d', global is %d\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
01665
01666
01667 pfd = mkstemp(tmp);
01668 if (pfd > -1) {
01669 p = fdopen(pfd, "w");
01670 if (!p) {
01671 close(pfd);
01672 pfd = -1;
01673 }
01674 }
01675 if (p) {
01676 gethostname(host, sizeof(host)-1);
01677 if (strchr(srcemail, '@'))
01678 ast_copy_string(who, srcemail, sizeof(who));
01679 else {
01680 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
01681 }
01682 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01683 time(&t);
01684
01685
01686 if (!ast_strlen_zero(vmu->zonetag)) {
01687
01688 struct vm_zone *z;
01689 z = zones;
01690 while (z) {
01691 if (!strcmp(z->name, vmu->zonetag)) {
01692 the_zone = z;
01693 break;
01694 }
01695 z = z->next;
01696 }
01697 }
01698
01699 if (the_zone)
01700 ast_localtime(&t,&tm,the_zone->timezone);
01701 else
01702 ast_localtime(&t,&tm,NULL);
01703 strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
01704 fprintf(p, "Date: %s\n", date);
01705
01706
01707 strftime(date, sizeof(date), emaildateformat, &tm);
01708
01709 if (*fromstring) {
01710 struct ast_channel *ast = ast_channel_alloc(0);
01711 if (ast) {
01712 char *passdata;
01713 int vmlen = strlen(fromstring)*3 + 200;
01714 if ((passdata = alloca(vmlen))) {
01715 memset(passdata, 0, vmlen);
01716 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01717 pbx_substitute_variables_helper(ast,fromstring,passdata,vmlen);
01718 fprintf(p, "From: %s <%s>\n",passdata,who);
01719 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01720 ast_channel_free(ast);
01721 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01722 } else
01723 fprintf(p, "From: Asterisk PBX <%s>\n", who);
01724 fprintf(p, "To: %s <%s>\n", vmu->fullname, vmu->email);
01725
01726 if (emailsubject) {
01727 struct ast_channel *ast = ast_channel_alloc(0);
01728 if (ast) {
01729 char *passdata;
01730 int vmlen = strlen(emailsubject)*3 + 200;
01731 if ((passdata = alloca(vmlen))) {
01732 memset(passdata, 0, vmlen);
01733 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01734 pbx_substitute_variables_helper(ast,emailsubject,passdata,vmlen);
01735 fprintf(p, "Subject: %s\n",passdata);
01736 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01737 ast_channel_free(ast);
01738 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01739 } else
01740 if (*emailtitle) {
01741 fprintf(p, emailtitle, msgnum + 1, mailbox) ;
01742 fprintf(p,"\n") ;
01743 } else if (ast_test_flag((&globalflags), VM_PBXSKIP))
01744 fprintf(p, "Subject: New message %d in mailbox %s\n", msgnum + 1, mailbox);
01745 else
01746 fprintf(p, "Subject: [PBX]: New message %d in mailbox %s\n", msgnum + 1, mailbox);
01747 fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>\n", msgnum, (unsigned int)rand(), mailbox, getpid(), host);
01748 fprintf(p, "MIME-Version: 1.0\n");
01749 if (attach_user_voicemail) {
01750
01751 snprintf(bound, sizeof(bound), "voicemail_%d%s%d%d", msgnum, mailbox, getpid(), (unsigned int)rand());
01752
01753 fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"\n\n\n", bound);
01754
01755 fprintf(p, "--%s\n", bound);
01756 }
01757 fprintf(p, "Content-Type: text/plain; charset=%s\nContent-Transfer-Encoding: 8bit\n\n", charset);
01758 if (emailbody) {
01759 struct ast_channel *ast = ast_channel_alloc(0);
01760 if (ast) {
01761 char *passdata;
01762 int vmlen = strlen(emailbody)*3 + 200;
01763 if ((passdata = alloca(vmlen))) {
01764 memset(passdata, 0, vmlen);
01765 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01766 pbx_substitute_variables_helper(ast,emailbody,passdata,vmlen);
01767 fprintf(p, "%s\n",passdata);
01768 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01769 ast_channel_free(ast);
01770 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01771 } else {
01772 fprintf(p, "Dear %s:\n\n\tJust wanted to let you know you were just left a %s long message (number %d)\n"
01773
01774 "in mailbox %s from %s, on %s so you might\n"
01775 "want to check it when you get a chance. Thanks!\n\n\t\t\t\t--Asterisk\n\n", vmu->fullname,
01776 dur, msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
01777 }
01778 if (attach_user_voicemail) {
01779
01780 char *ctype = "audio/x-";
01781 if (!strcasecmp(format, "ogg"))
01782 ctype = "application/";
01783
01784 fprintf(p, "--%s\n", bound);
01785 fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"\n", ctype, format, msgnum, format);
01786 fprintf(p, "Content-Transfer-Encoding: base64\n");
01787 fprintf(p, "Content-Description: Voicemail sound attachment.\n");
01788 fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"\n\n", msgnum, format);
01789
01790 snprintf(fname, sizeof(fname), "%s.%s", attach, format);
01791 base_encode(fname, p);
01792 fprintf(p, "\n\n--%s--\n.\n", bound);
01793 }
01794 fclose(p);
01795 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
01796 ast_safe_system(tmp2);
01797 ast_log(LOG_DEBUG, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
01798 } else {
01799 ast_log(LOG_WARNING, "Unable to launch '%s'\n", mailcmd);
01800 return -1;
01801 }
01802 return 0;
01803 }
01804
01805 static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu)
01806 {
01807 FILE *p=NULL;
01808 int pfd;
01809 char date[256];
01810 char host[MAXHOSTNAMELEN]="";
01811 char who[256];
01812 char dur[256];
01813 char tmp[80] = "/tmp/astmail-XXXXXX";
01814 char tmp2[256];
01815 time_t t;
01816 struct tm tm;
01817 struct vm_zone *the_zone = NULL;
01818 pfd = mkstemp(tmp);
01819
01820 if (pfd > -1) {
01821 p = fdopen(pfd, "w");
01822 if (!p) {
01823 close(pfd);
01824 pfd = -1;
01825 }
01826 }
01827
01828 if (p) {
01829 gethostname(host, sizeof(host)-1);
01830 if (strchr(srcemail, '@'))
01831 ast_copy_string(who, srcemail, sizeof(who));
01832 else {
01833 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
01834 }
01835 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01836 time(&t);
01837
01838
01839 if (!ast_strlen_zero(vmu->zonetag)) {
01840
01841 struct vm_zone *z;
01842 z = zones;
01843 while (z) {
01844 if (!strcmp(z->name, vmu->zonetag)) {
01845 the_zone = z;
01846 break;
01847 }
01848 z = z->next;
01849 }
01850 }
01851
01852 if (the_zone)
01853 ast_localtime(&t,&tm,the_zone->timezone);
01854 else
01855 ast_localtime(&t,&tm,NULL);
01856
01857 strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", &tm);
01858 fprintf(p, "Date: %s\n", date);
01859
01860 if (*pagerfromstring) {
01861 struct ast_channel *ast = ast_channel_alloc(0);
01862 if (ast) {
01863 char *passdata;
01864 int vmlen = strlen(fromstring)*3 + 200;
01865 if ((passdata = alloca(vmlen))) {
01866 memset(passdata, 0, vmlen);
01867 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01868 pbx_substitute_variables_helper(ast,pagerfromstring,passdata,vmlen);
01869 fprintf(p, "From: %s <%s>\n",passdata,who);
01870 } else
01871 ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01872 ast_channel_free(ast);
01873 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01874 } else
01875 fprintf(p, "From: Asterisk PBX <%s>\n", who);
01876 fprintf(p, "To: %s\n", pager);
01877 if (pagersubject) {
01878 struct ast_channel *ast = ast_channel_alloc(0);
01879 if (ast) {
01880 char *passdata;
01881 int vmlen = strlen(pagersubject)*3 + 200;
01882 if ((passdata = alloca(vmlen))) {
01883 memset(passdata, 0, vmlen);
01884 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01885 pbx_substitute_variables_helper(ast,pagersubject,passdata,vmlen);
01886 fprintf(p, "Subject: %s\n\n",passdata);
01887 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01888 ast_channel_free(ast);
01889 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01890 } else
01891 fprintf(p, "Subject: New VM\n\n");
01892 strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
01893 if (pagerbody) {
01894 struct ast_channel *ast = ast_channel_alloc(0);
01895 if (ast) {
01896 char *passdata;
01897 int vmlen = strlen(pagerbody)*3 + 200;
01898 if ((passdata = alloca(vmlen))) {
01899 memset(passdata, 0, vmlen);
01900 prep_email_sub_vars(ast,vmu,msgnum + 1,context,mailbox,cidnum, cidname,dur,date,passdata, vmlen);
01901 pbx_substitute_variables_helper(ast,pagerbody,passdata,vmlen);
01902 fprintf(p, "%s\n",passdata);
01903 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01904 ast_channel_free(ast);
01905 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01906 } else {
01907 fprintf(p, "New %s long msg in box %s\n"
01908 "from %s, on %s", dur, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
01909 }
01910 fclose(p);
01911 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
01912 ast_safe_system(tmp2);
01913 ast_log(LOG_DEBUG, "Sent page to %s with command '%s'\n", pager, mailcmd);
01914 } else {
01915 ast_log(LOG_WARNING, "Unable to launch '%s'\n", mailcmd);
01916 return -1;
01917 }
01918 return 0;
01919 }
01920
01921 static int get_date(char *s, int len)
01922 {
01923 struct tm tm;
01924 time_t t;
01925 t = time(0);
01926 localtime_r(&t,&tm);
01927 return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
01928 }
01929
01930 static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
01931 {
01932 int res;
01933 char fn[256];
01934 snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
01935 RETRIEVE(fn, -1);
01936 if (ast_fileexists(fn, NULL, NULL) > 0) {
01937 res = ast_streamfile(chan, fn, chan->language);
01938 if (res) {
01939 DISPOSE(fn, -1);
01940 return -1;
01941 }
01942 res = ast_waitstream(chan, ecodes);
01943 if (res) {
01944 DISPOSE(fn, -1);
01945 return res;
01946 }
01947 } else {
01948
01949 DISPOSE(fn, -1);
01950 res = ast_streamfile(chan, "vm-theperson", chan->language);
01951 if (res)
01952 return -1;
01953 res = ast_waitstream(chan, ecodes);
01954 if (res)
01955 return res;
01956 res = ast_say_digit_str(chan, ext, ecodes, chan->language);
01957 if (res)
01958 return res;
01959 }
01960 if (busy)
01961 res = ast_streamfile(chan, "vm-isonphone", chan->language);
01962 else
01963 res = ast_streamfile(chan, "vm-isunavail", chan->language);
01964 if (res)
01965 return -1;
01966 res = ast_waitstream(chan, ecodes);
01967 return res;
01968 }
01969
01970 static void free_user(struct ast_vm_user *vmu)
01971 {
01972 if (ast_test_flag(vmu, VM_ALLOCED))
01973 free(vmu);
01974 }
01975
01976 static void free_zone(struct vm_zone *z)
01977 {
01978 free(z);
01979 }
01980
01981 static char *mbox(int id)
01982 {
01983 switch(id) {
01984 case 0:
01985 return "INBOX";
01986 case 1:
01987 return "Old";
01988 case 2:
01989 return "Work";
01990 case 3:
01991 return "Family";
01992 case 4:
01993 return "Friends";
01994 case 5:
01995 return "Cust1";
01996 case 6:
01997 return "Cust2";
01998 case 7:
01999 return "Cust3";
02000 case 8:
02001 return "Cust4";
02002 case 9:
02003 return "Cust5";
02004 default:
02005 return "Unknown";
02006 }
02007 }
02008
02009 #ifdef USE_ODBC_STORAGE
02010 static int messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
02011 {
02012 int x = 0;
02013 int res;
02014 SQLHSTMT stmt;
02015 char sql[256];
02016 char rowdata[20];
02017 char tmp[256]="";
02018 char *context;
02019
02020 if (newmsgs)
02021 *newmsgs = 0;
02022 if (oldmsgs)
02023 *oldmsgs = 0;
02024
02025 if (ast_strlen_zero(mailbox))
02026 return 0;
02027
02028 ast_copy_string(tmp, mailbox, sizeof(tmp));
02029
02030 context = strchr(tmp, '@');
02031 if (context) {
02032 *context = '\0';
02033 context++;
02034 } else
02035 context = "default";
02036
02037 odbc_obj *obj;
02038 obj = fetch_odbc_obj(odbc_database, 0);
02039 if (obj) {
02040 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
02041 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02042 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
02043 goto yuck;
02044 }
02045 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir LIKE '%%%s/%s/%s'", odbc_table, context, tmp, "INBOX");
02046 res = SQLPrepare(stmt, sql, SQL_NTS);
02047 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02048 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
02049 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02050 goto yuck;
02051 }
02052 res = odbc_smart_execute(obj, stmt);
02053 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02054 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02055 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02056 goto yuck;
02057 }
02058 res = SQLFetch(stmt);
02059 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02060 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02061 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02062 goto yuck;
02063 }
02064 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02065 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02066 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02067 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02068 goto yuck;
02069 }
02070 *newmsgs = atoi(rowdata);
02071 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02072
02073 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
02074 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02075 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
02076 goto yuck;
02077 }
02078 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir like '%%%s/%s/%s'", odbc_table, context, tmp, "Old");
02079 res = SQLPrepare(stmt, sql, SQL_NTS);
02080 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02081 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
02082 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02083 goto yuck;
02084 }
02085 res = odbc_smart_execute(obj, stmt);
02086 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02087 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02088 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02089 goto yuck;
02090 }
02091 res = SQLFetch(stmt);
02092 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02093 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02094 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02095 goto yuck;
02096 }
02097 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02098 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02099 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02100 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02101 goto yuck;
02102 }
02103 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02104 *oldmsgs = atoi(rowdata);
02105 x = 1;
02106 } else
02107 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
02108
02109 yuck:
02110 return x;
02111 }
02112
02113 static int has_voicemail(const char *mailbox, const char *folder)
02114 {
02115 int nummsgs = 0;
02116 int res;
02117 SQLHSTMT stmt;
02118 char sql[256];
02119 char rowdata[20];
02120 char tmp[256]="";
02121 char *context;
02122 if (!folder)
02123 folder = "INBOX";
02124
02125 if (ast_strlen_zero(mailbox))
02126 return 0;
02127
02128 ast_copy_string(tmp, mailbox, sizeof(tmp));
02129
02130 context = strchr(tmp, '@');
02131 if (context) {
02132 *context = '\0';
02133 context++;
02134 } else
02135 context = "default";
02136
02137 odbc_obj *obj;
02138 obj = fetch_odbc_obj(odbc_database, 0);
02139 if (obj) {
02140 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
02141 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02142 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
02143 goto yuck;
02144 }
02145 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir like '%%%s/%s/%s'", odbc_table, context, tmp, "INBOX");
02146 res = SQLPrepare(stmt, sql, SQL_NTS);
02147 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02148 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
02149 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02150 goto yuck;
02151 }
02152 res = odbc_smart_execute(obj, stmt);
02153 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02154 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02155 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02156 goto yuck;
02157 }
02158 res = SQLFetch(stmt);
02159 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02160 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02161 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02162 goto yuck;
02163 }
02164 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02165 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02166 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02167 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02168 goto yuck;
02169 }
02170 nummsgs = atoi(rowdata);
02171 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02172 } else
02173 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
02174
02175 yuck:
02176 if (nummsgs>=1)
02177 return 1;
02178 else
02179 return 0;
02180 }
02181
02182 #else
02183
02184 static int has_voicemail(const char *mailbox, const char *folder)
02185 {
02186 DIR *dir;
02187 struct dirent *de;
02188 char fn[256];
02189 char tmp[256]="";
02190 char *mb, *cur;
02191 char *context;
02192 int ret;
02193 if (!folder)
02194 folder = "INBOX";
02195
02196 if (ast_strlen_zero(mailbox))
02197 return 0;
02198 if (strchr(mailbox, ',')) {
02199 ast_copy_string(tmp, mailbox, sizeof(tmp));
02200 mb = tmp;
02201 ret = 0;
02202 while((cur = strsep(&mb, ","))) {
02203 if (!ast_strlen_zero(cur)) {
02204 if (has_voicemail(cur, folder))
02205 return 1;
02206 }
02207 }
02208 return 0;
02209 }
02210 ast_copy_string(tmp, mailbox, sizeof(tmp));
02211 context = strchr(tmp, '@');
02212 if (context) {
02213 *context = '\0';
02214 context++;
02215 } else
02216 context = "default";
02217 snprintf(fn, sizeof(fn), "%s/%s/%s/%s", VM_SPOOL_DIR, context, tmp, folder);
02218 dir = opendir(fn);
02219 if (!dir)
02220 return 0;
02221 while ((de = readdir(dir))) {
02222 if (!strncasecmp(de->d_name, "msg", 3))
02223 break;
02224 }
02225 closedir(dir);
02226 if (de)
02227 return 1;
02228 return 0;
02229 }
02230
02231
02232 static int messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
02233 {
02234 DIR *dir;
02235 struct dirent *de;
02236 char fn[256];
02237 char tmp[256]="";
02238 char *mb, *cur;
02239 char *context;
02240 int ret;
02241 if (newmsgs)
02242 *newmsgs = 0;
02243 if (oldmsgs)
02244 *oldmsgs = 0;
02245
02246 if (ast_strlen_zero(mailbox))
02247 return 0;
02248 if (strchr(mailbox, ',')) {
02249 int tmpnew, tmpold;
02250 ast_copy_string(tmp, mailbox, sizeof(tmp));
02251 mb = tmp;
02252 ret = 0;
02253 while((cur = strsep(&mb, ", "))) {
02254 if (!ast_strlen_zero(cur)) {
02255 if (messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
02256 return -1;
02257 else {
02258 if (newmsgs)
02259 *newmsgs += tmpnew;
02260 if (oldmsgs)
02261 *oldmsgs += tmpold;
02262 }
02263 }
02264 }
02265 return 0;
02266 }
02267 ast_copy_string(tmp, mailbox, sizeof(tmp));
02268 context = strchr(tmp, '@');
02269 if (context) {
02270 *context = '\0';
02271 context++;
02272 } else
02273 context = "default";
02274 if (newmsgs) {
02275 snprintf(fn, sizeof(fn), "%s/%s/%s/INBOX", VM_SPOOL_DIR, context, tmp);
02276 dir = opendir(fn);
02277 if (dir) {
02278 while ((de = readdir(dir))) {
02279 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
02280 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
02281 (*newmsgs)++;
02282
02283 }
02284 closedir(dir);
02285 }
02286 }
02287 if (oldmsgs) {
02288 snprintf(fn, sizeof(fn), "%s/%s/%s/Old", VM_SPOOL_DIR, context, tmp);
02289 dir = opendir(fn);
02290 if (dir) {
02291 while ((de = readdir(dir))) {
02292 if ((strlen(de->d_name) > 3) && !strncasecmp(de->d_name, "msg", 3) &&
02293 !strcasecmp(de->d_name + strlen(de->d_name) - 3, "txt"))
02294 (*oldmsgs)++;
02295
02296 }
02297 closedir(dir);
02298 }
02299 }
02300 return 0;
02301 }
02302
02303 #endif
02304
02305 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
02306
02307 static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt)
02308 {
02309 char fromdir[256], todir[256], frompath[256], topath[256];
02310 char *frombox = mbox(imbox);
02311 int recipmsgnum;
02312
02313 ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
02314
02315 create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
02316
02317 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
02318 make_file(frompath, sizeof(frompath), fromdir, msgnum);
02319
02320 if (vm_lock_path(todir))
02321 return ERROR_LOCK_PATH;
02322
02323 recipmsgnum = 0;
02324 do {
02325 make_file(topath, sizeof(topath), todir, recipmsgnum);
02326 if (!EXISTS(todir, recipmsgnum, topath, chan->language))
02327 break;
02328 recipmsgnum++;
02329 } while (recipmsgnum < recip->maxmsg);
02330 if (recipmsgnum < recip->maxmsg) {
02331 COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
02332 } else {
02333 ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
02334 }
02335 ast_unlock_path(todir);
02336 notify_new_message(chan, recip, recipmsgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
02337
02338 return 0;
02339 }
02340
02341 static void run_externnotify(char *context, char *extension)
02342 {
02343 char arguments[255];
02344 char ext_context[256] = "";
02345 int newvoicemails = 0, oldvoicemails = 0;
02346
02347 if (!ast_strlen_zero(context))
02348 snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
02349 else
02350 ast_copy_string(ext_context, extension, sizeof(ext_context));
02351
02352 if (!ast_strlen_zero(externnotify)) {
02353 if (messagecount(ext_context, &newvoicemails, &oldvoicemails)) {
02354 ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
02355 } else {
02356 snprintf(arguments, sizeof(arguments), "%s %s %s %d&", externnotify, context, extension, newvoicemails);
02357 ast_log(LOG_DEBUG, "Executing %s\n", arguments);
02358 ast_safe_system(arguments);
02359 }
02360 }
02361 }
02362
02363 struct leave_vm_options {
02364 unsigned int flags;
02365 signed char record_gain;
02366 };
02367
02368 static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
02369 {
02370 char txtfile[256];
02371 char callerid[256];
02372 FILE *txt;
02373 int res = 0;
02374 int msgnum;
02375 int duration = 0;
02376 int ausemacro = 0;
02377 int ousemacro = 0;
02378 char date[256];
02379 char dir[256];
02380 char fn[256];
02381 char prefile[256]="";
02382 char tempfile[256]="";
02383 char ext_context[256] = "";
02384 char fmt[80];
02385 char *context;
02386 char ecodes[16] = "#";
02387 char tmp[256] = "", *tmpptr;
02388 struct ast_vm_user *vmu;
02389 struct ast_vm_user svm;
02390 char *category = NULL;
02391
02392 ast_copy_string(tmp, ext, sizeof(tmp));
02393 ext = tmp;
02394 context = strchr(tmp, '@');
02395 if (context) {
02396 *context = '\0';
02397 context++;
02398 tmpptr = strchr(context, '&');
02399 } else {
02400 tmpptr = strchr(ext, '&');
02401 }
02402
02403 if (tmpptr) {
02404 *tmpptr = '\0';
02405 tmpptr++;
02406 }
02407
02408 category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
02409
02410 if (!(vmu = find_user(&svm, context, ext))) {
02411 ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
02412 if (ast_test_flag(options, OPT_PRIORITY_JUMP) || option_priority_jumping)
02413 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
02414 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02415 return res;
02416 }
02417
02418
02419 if (strcmp(vmu->context, "default"))
02420 snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
02421 else
02422 ast_copy_string(ext_context, vmu->context, sizeof(ext_context));
02423 if (ast_test_flag(options, OPT_BUSY_GREETING))
02424 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
02425 else if (ast_test_flag(options, OPT_UNAVAIL_GREETING))
02426 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
02427 snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
02428 RETRIEVE(tempfile, -1);
02429 if (ast_fileexists(tempfile, NULL, NULL) > 0)
02430 ast_copy_string(prefile, tempfile, sizeof(prefile));
02431 DISPOSE(tempfile, -1);
02432
02433 create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
02434
02435
02436 if (!ast_strlen_zero(vmu->exit)) {
02437 if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num))
02438 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02439 } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num))
02440 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02441 else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
02442 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02443 ousemacro = 1;
02444 }
02445
02446 if (!ast_strlen_zero(vmu->exit)) {
02447 if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
02448 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02449 } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
02450 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02451 else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
02452 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02453 ausemacro = 1;
02454 }
02455
02456
02457 if (!ast_strlen_zero(prefile)) {
02458 RETRIEVE(prefile, -1);
02459 if (ast_fileexists(prefile, NULL, NULL) > 0) {
02460 if (ast_streamfile(chan, prefile, chan->language) > -1)
02461 res = ast_waitstream(chan, ecodes);
02462 } else {
02463 ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
02464 res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
02465 }
02466 DISPOSE(prefile, -1);
02467 if (res < 0) {
02468 ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
02469 free_user(vmu);
02470 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02471 return -1;
02472 }
02473 }
02474 if (res == '#') {
02475
02476 ast_set_flag(options, OPT_SILENT);
02477 res = 0;
02478 }
02479 if (!res && !ast_test_flag(options, OPT_SILENT)) {
02480 res = ast_streamfile(chan, INTRO, chan->language);
02481 if (!res)
02482 res = ast_waitstream(chan, ecodes);
02483 if (res == '#') {
02484 ast_set_flag(options, OPT_SILENT);
02485 res = 0;
02486 }
02487 }
02488 if (res > 0)
02489 ast_stopstream(chan);
02490
02491
02492 if (res == '*') {
02493 chan->exten[0] = 'a';
02494 chan->exten[1] = '\0';
02495 if (!ast_strlen_zero(vmu->exit)) {
02496 ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02497 } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
02498 ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02499 }
02500 chan->priority = 0;
02501 free_user(vmu);
02502 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
02503 return 0;
02504 }
02505
02506 if (res == '0') {
02507 transfer:
02508 if (ast_test_flag(vmu, VM_OPERATOR)) {
02509 chan->exten[0] = 'o';
02510 chan->exten[1] = '\0';
02511 if (!ast_strlen_zero(vmu->exit)) {
02512 ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02513 } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
02514 ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02515 }
02516 ast_play_and_wait(chan, "transfer");
02517 chan->priority = 0;
02518 free_user(vmu);
02519 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
02520 return 0;
02521 } else {
02522 ast_play_and_wait(chan, "vm-sorry");
02523 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
02524 return 0;
02525 }
02526 }
02527 if (res < 0) {
02528 free_user(vmu);
02529 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02530 return -1;
02531 }
02532
02533 ast_copy_string(fmt, vmfmts, sizeof(fmt));
02534 if (!ast_strlen_zero(fmt)) {
02535 msgnum = 0;
02536
02537 if (vm_lock_path(dir)) {
02538 free_user(vmu);
02539 return ERROR_LOCK_PATH;
02540 }
02541
02542
02543
02544
02545
02546
02547 do {
02548 make_file(fn, sizeof(fn), dir, msgnum);
02549 if (!EXISTS(dir,msgnum,fn,chan->language))
02550 break;
02551 msgnum++;
02552 } while (msgnum < vmu->maxmsg);
02553
02554
02555 if (res >= 0) {
02556
02557 res = ast_streamfile(chan, "beep", chan->language);
02558 if (!res)
02559 res = ast_waitstream(chan, "");
02560 }
02561 if (msgnum < vmu->maxmsg) {
02562
02563 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
02564
02565
02566 snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
02567 txt = fopen(txtfile, "w+");
02568 if (txt) {
02569 get_date(date, sizeof(date));
02570 fprintf(txt,
02571 ";\n"
02572 "; Message Information file\n"
02573 ";\n"
02574 "[message]\n"
02575 "origmailbox=%s\n"
02576 "context=%s\n"
02577 "macrocontext=%s\n"
02578 "exten=%s\n"
02579 "priority=%d\n"
02580 "callerchan=%s\n"
02581 "callerid=%s\n"
02582 "origdate=%s\n"
02583 "origtime=%ld\n"
02584 "category=%s\n",
02585 ext,
02586 chan->context,
02587 chan->macrocontext,
02588 chan->exten,
02589 chan->priority,
02590 chan->name,
02591 ast_callerid_merge(callerid, sizeof(callerid), chan->cid.cid_name, chan->cid.cid_num, "Unknown"),
02592 date, (long)time(NULL),
02593 category ? category : "");
02594 } else
02595 ast_log(LOG_WARNING, "Error opening text file for output\n");
02596 res = play_record_review(chan, NULL, fn, vmmaxmessage, fmt, 1, vmu, &duration, dir, options->record_gain);
02597 if (res == '0') {
02598 if (txt)
02599 fclose(txt);
02600 goto transfer;
02601 }
02602 if (res > 0)
02603 res = 0;
02604 if (txt) {
02605 fprintf(txt, "duration=%d\n", duration);
02606 fclose(txt);
02607 }
02608
02609 if (duration < vmminmessage) {
02610 if (option_verbose > 2)
02611 ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
02612 DELETE(dir,msgnum,fn);
02613
02614 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02615 goto leave_vm_out;
02616 }
02617
02618 while (tmpptr) {
02619 struct ast_vm_user recipu, *recip;
02620 char *exten, *context;
02621
02622 exten = strsep(&tmpptr, "&");
02623 context = strchr(exten, '@');
02624 if (context) {
02625 *context = '\0';
02626 context++;
02627 }
02628 if ((recip = find_user(&recipu, context, exten))) {
02629 copy_message(chan, vmu, 0, msgnum, duration, recip, fmt);
02630 free_user(recip);
02631 }
02632 }
02633 if (ast_fileexists(fn, NULL, NULL)) {
02634 STORE(dir, vmu->mailbox, vmu->context, msgnum);
02635 notify_new_message(chan, vmu, msgnum, duration, fmt, chan->cid.cid_num, chan->cid.cid_name);
02636 DISPOSE(dir, msgnum);
02637 }
02638 pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
02639 } else {
02640 ast_unlock_path(dir);
02641 res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
02642 if (!res)
02643 res = ast_waitstream(chan, "");
02644 ast_log(LOG_WARNING, "No more messages possible\n");
02645 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02646 }
02647 } else
02648 ast_log(LOG_WARNING, "No format for saving voicemail?\n");
02649 leave_vm_out:
02650 free_user(vmu);
02651
02652 return res;
02653 }
02654
02655 static int resequence_mailbox(struct ast_vm_user *vmu, char *dir)
02656 {
02657
02658
02659 int x,dest;
02660 char sfn[256];
02661 char dfn[256];
02662
02663 if (vm_lock_path(dir))
02664 return ERROR_LOCK_PATH;
02665
02666 for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
02667 make_file(sfn, sizeof(sfn), dir, x);
02668 if (EXISTS(dir, x, sfn, NULL)) {
02669
02670 if(x != dest) {
02671 make_file(dfn, sizeof(dfn), dir, dest);
02672 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
02673 }
02674
02675 dest++;
02676 }
02677 }
02678 ast_unlock_path(dir);
02679
02680 return 0;
02681 }
02682
02683
02684 static int say_and_wait(struct ast_channel *chan, int num, char *language)
02685 {
02686 int d;
02687 d = ast_say_number(chan, num, AST_DIGIT_ANY, language, (char *) NULL);
02688 return d;
02689 }
02690
02691 static int save_to_folder(struct ast_vm_user *vmu, char *dir, int msg, char *context, char *username, int box)
02692 {
02693 char sfn[256];
02694 char dfn[256];
02695 char ddir[256];
02696 char *dbox = mbox(box);
02697 int x;
02698 make_file(sfn, sizeof(sfn), dir, msg);
02699 create_dirpath(ddir, sizeof(ddir), context, username, dbox);
02700
02701 if (vm_lock_path(ddir))
02702 return ERROR_LOCK_PATH;
02703
02704 for (x = 0; x < vmu->maxmsg; x++) {
02705 make_file(dfn, sizeof(dfn), ddir, x);
02706 if (!EXISTS(ddir, x, dfn, NULL))
02707 break;
02708 }
02709 if (x >= vmu->maxmsg) {
02710 ast_unlock_path(ddir);
02711 return -1;
02712 }
02713 if (strcmp(sfn, dfn)) {
02714 COPY(dir, msg, ddir, x, username, context, sfn, dfn);
02715 }
02716 ast_unlock_path(ddir);
02717
02718 return 0;
02719 }
02720
02721 static int adsi_logo(unsigned char *buf)
02722 {
02723 int bytes = 0;
02724 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
02725 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002 LSS, Inc.", "");
02726 return bytes;
02727 }
02728
02729 static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
02730 {
02731 unsigned char buf[256];
02732 int bytes=0;
02733 int x;
02734 char num[5];
02735
02736 *useadsi = 0;
02737 bytes += adsi_data_mode(buf + bytes);
02738 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02739
02740 bytes = 0;
02741 bytes += adsi_logo(buf);
02742 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
02743 #ifdef DISPLAY
02744 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
02745 #endif
02746 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02747 bytes += adsi_data_mode(buf + bytes);
02748 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02749
02750 if (adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
02751 bytes = 0;
02752 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
02753 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
02754 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02755 bytes += adsi_voice_mode(buf + bytes, 0);
02756 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02757 return 0;
02758 }
02759
02760 #ifdef DISPLAY
02761
02762 bytes = 0;
02763 bytes += adsi_logo(buf);
02764 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
02765 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
02766 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02767 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02768 #endif
02769 bytes = 0;
02770 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
02771 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
02772 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
02773 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
02774 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
02775 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
02776 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
02777
02778 #ifdef DISPLAY
02779
02780 bytes = 0;
02781 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
02782 bytes += adsi_voice_mode(buf + bytes, 0);
02783
02784 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02785 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02786 #endif
02787
02788 bytes = 0;
02789
02790 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
02791 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
02792 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
02793 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
02794 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
02795 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
02796 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
02797
02798 #ifdef DISPLAY
02799
02800 bytes = 0;
02801 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
02802 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02803 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02804 #endif
02805
02806 bytes = 0;
02807 for (x=0;x<5;x++) {
02808 snprintf(num, sizeof(num), "%d", x);
02809 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
02810 }
02811 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
02812 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
02813
02814 #ifdef DISPLAY
02815
02816 bytes = 0;
02817 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
02818 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02819 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02820 #endif
02821
02822 if (adsi_end_download(chan)) {
02823 bytes = 0;
02824 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
02825 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
02826 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02827 bytes += adsi_voice_mode(buf + bytes, 0);
02828 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02829 return 0;
02830 }
02831 bytes = 0;
02832 bytes += adsi_download_disconnect(buf + bytes);
02833 bytes += adsi_voice_mode(buf + bytes, 0);
02834 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
02835
02836 ast_log(LOG_DEBUG, "Done downloading scripts...\n");
02837
02838 #ifdef DISPLAY
02839
02840 bytes = 0;
02841 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
02842 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02843 #endif
02844 ast_log(LOG_DEBUG, "Restarting session...\n");
02845
02846 bytes = 0;
02847
02848 if (adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
02849 *useadsi = 1;
02850 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
02851 } else
02852 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
02853
02854 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02855 return 0;
02856 }
02857
02858 static void adsi_begin(struct ast_channel *chan, int *useadsi)
02859 {
02860 int x;
02861 if (!adsi_available(chan))
02862 return;
02863 x = adsi_load_session(chan, adsifdn, adsiver, 1);
02864 if (x < 0)
02865 return;
02866 if (!x) {
02867 if (adsi_load_vmail(chan, useadsi)) {
02868 ast_log(LOG_WARNING, "Unable to upload voicemail scripts\n");
02869 return;
02870 }
02871 } else
02872 *useadsi = 1;
02873 }
02874
02875 static void adsi_login(struct ast_channel *chan)
02876 {
02877 unsigned char buf[256];
02878 int bytes=0;
02879 unsigned char keys[8];
02880 int x;
02881 if (!adsi_available(chan))
02882 return;
02883
02884 for (x=0;x<8;x++)
02885 keys[x] = 0;
02886
02887 keys[3] = ADSI_KEY_APPS + 3;
02888
02889 bytes += adsi_logo(buf + bytes);
02890 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
02891 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
02892 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02893 bytes += adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
02894 bytes += adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
02895 bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
02896 bytes += adsi_set_keys(buf + bytes, keys);
02897 bytes += adsi_voice_mode(buf + bytes, 0);
02898 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02899 }
02900
02901 static void adsi_password(struct ast_channel *chan)
02902 {
02903 unsigned char buf[256];
02904 int bytes=0;
02905 unsigned char keys[8];
02906 int x;
02907 if (!adsi_available(chan))
02908 return;
02909
02910 for (x=0;x<8;x++)
02911 keys[x] = 0;
02912
02913 keys[3] = ADSI_KEY_APPS + 3;
02914
02915 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02916 bytes += adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
02917 bytes += adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
02918 bytes += adsi_set_keys(buf + bytes, keys);
02919 bytes += adsi_voice_mode(buf + bytes, 0);
02920 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02921 }
02922
02923 static void adsi_folders(struct ast_channel *chan, int start, char *label)
02924 {
02925 unsigned char buf[256];
02926 int bytes=0;
02927 unsigned char keys[8];
02928 int x,y;
02929
02930 if (!adsi_available(chan))
02931 return;
02932
02933 for (x=0;x<5;x++) {
02934 y = ADSI_KEY_APPS + 12 + start + x;
02935 if (y > ADSI_KEY_APPS + 12 + 4)
02936 y = 0;
02937 keys[x] = ADSI_KEY_SKT | y;
02938 }
02939 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
02940 keys[6] = 0;
02941 keys[7] = 0;
02942
02943 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
02944 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
02945 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
02946 bytes += adsi_set_keys(buf + bytes, keys);
02947 bytes += adsi_voice_mode(buf + bytes, 0);
02948
02949 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
02950 }
02951
02952 static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
02953 {
02954 int bytes=0;
02955 unsigned char buf[256];
02956 char buf1[256], buf2[256];
02957 char fn2[256];
02958
02959 char cid[256]="";
02960 char *val;
02961 char *name, *num;
02962 char datetime[21]="";
02963 FILE *f;
02964
02965 unsigned char keys[8];
02966
02967 int x;
02968
02969 if (!adsi_available(chan))
02970 return;
02971
02972
02973 snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
02974 f = fopen(fn2, "r");
02975 if (f) {
02976 while (!feof(f)) {
02977 fgets((char *)buf, sizeof(buf), f);
02978 if (!feof(f)) {
02979 char *stringp=NULL;
02980 stringp = (char *)buf;
02981 strsep(&stringp, "=");
02982 val = strsep(&stringp, "=");
02983 if (!ast_strlen_zero(val)) {
02984 if (!strcmp((char *)buf, "callerid"))
02985 ast_copy_string(cid, val, sizeof(cid));
02986 if (!strcmp((char *)buf, "origdate"))
02987 ast_copy_string(datetime, val, sizeof(datetime));
02988 }
02989 }
02990 }
02991 fclose(f);
02992 }
02993
02994 for (x=0;x<5;x++)
02995 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
02996 keys[6] = 0x0;
02997 keys[7] = 0x0;
02998
02999 if (!vms->curmsg) {
03000
03001 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03002 }
03003 if (vms->curmsg >= vms->lastmsg) {
03004
03005 if (vms->curmsg) {
03006
03007 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03008 bytes += adsi_voice_mode(buf + bytes, 0);
03009
03010 } else {
03011
03012 keys[3] = 1;
03013 }
03014 }
03015
03016 if (!ast_strlen_zero(cid)) {
03017 ast_callerid_parse(cid, &name, &num);
03018 if (!name)
03019 name = num;
03020 } else
03021 name = "Unknown Caller";
03022
03023
03024
03025 if (vms->deleted[vms->curmsg])
03026 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
03027
03028
03029 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
03030 snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
03031 strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
03032 snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
03033
03034 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03035 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03036 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
03037 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
03038 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03039 bytes += adsi_set_keys(buf + bytes, keys);
03040 bytes += adsi_voice_mode(buf + bytes, 0);
03041
03042 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03043 }
03044
03045 static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
03046 {
03047 int bytes=0;
03048 unsigned char buf[256];
03049 unsigned char keys[8];
03050
03051 int x;
03052
03053 if (!adsi_available(chan))
03054 return;
03055
03056
03057 for (x=0;x<5;x++)
03058 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
03059
03060 keys[6] = 0x0;
03061 keys[7] = 0x0;
03062
03063 if (!vms->curmsg) {
03064
03065 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03066 }
03067 if (vms->curmsg >= vms->lastmsg) {
03068
03069 if (vms->curmsg) {
03070
03071 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03072 } else {
03073
03074 keys[3] = 1;
03075 }
03076 }
03077
03078
03079 if (vms->deleted[vms->curmsg])
03080 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
03081
03082
03083 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
03084 bytes += adsi_set_keys(buf + bytes, keys);
03085 bytes += adsi_voice_mode(buf + bytes, 0);
03086
03087 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03088 }
03089
03090 static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
03091 {
03092 unsigned char buf[256] = "";
03093 char buf1[256] = "", buf2[256] = "";
03094 int bytes=0;
03095 unsigned char keys[8];
03096 int x;
03097
03098 char *newm = (vms->newmessages == 1) ? "message" : "messages";
03099 char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
03100 if (!adsi_available(chan))
03101 return;
03102 if (vms->newmessages) {
03103 snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
03104 if (vms->oldmessages) {
03105 strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
03106 snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
03107 } else {
03108 snprintf(buf2, sizeof(buf2), "%s.", newm);
03109 }
03110 } else if (vms->oldmessages) {
03111 snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
03112 snprintf(buf2, sizeof(buf2), "%s.", oldm);
03113 } else {
03114 strcpy(buf1, "You have no messages.");
03115 buf2[0] = ' ';
03116 buf2[1] = '\0';
03117 }
03118 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03119 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03120 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03121
03122 for (x=0;x<6;x++)
03123 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
03124 keys[6] = 0;
03125 keys[7] = 0;
03126
03127
03128 if (vms->lastmsg < 0)
03129 keys[0] = 1;
03130 bytes += adsi_set_keys(buf + bytes, keys);
03131
03132 bytes += adsi_voice_mode(buf + bytes, 0);
03133
03134 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03135 }
03136
03137 static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
03138 {
03139 unsigned char buf[256] = "";
03140 char buf1[256] = "", buf2[256] = "";
03141 int bytes=0;
03142 unsigned char keys[8];
03143 int x;
03144
03145 char *mess = (vms->lastmsg == 0) ? "message" : "messages";
03146
03147 if (!adsi_available(chan))
03148 return;
03149
03150
03151 for (x=0;x<6;x++)
03152 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
03153
03154 keys[6] = 0;
03155 keys[7] = 0;
03156
03157 if ((vms->lastmsg + 1) < 1)
03158 keys[0] = 0;
03159
03160 snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
03161 strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
03162
03163 if (vms->lastmsg + 1)
03164 snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
03165 else
03166 strcpy(buf2, "no messages.");
03167 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03168 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03169 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
03170 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03171 bytes += adsi_set_keys(buf + bytes, keys);
03172
03173 bytes += adsi_voice_mode(buf + bytes, 0);
03174
03175 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03176
03177 }
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193 static void adsi_goodbye(struct ast_channel *chan)
03194 {
03195 unsigned char buf[256];
03196 int bytes=0;
03197
03198 if (!adsi_available(chan))
03199 return;
03200 bytes += adsi_logo(buf + bytes);
03201 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
03202 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
03203 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03204 bytes += adsi_voice_mode(buf + bytes, 0);
03205
03206 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03207 }
03208
03209
03210
03211
03212
03213 static int get_folder(struct ast_channel *chan, int start)
03214 {
03215 int x;
03216 int d;
03217 char fn[256];
03218 d = ast_play_and_wait(chan, "vm-press");
03219 if (d)
03220 return d;
03221 for (x = start; x< 5; x++) {
03222 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, (char *) NULL)))
03223 return d;
03224 d = ast_play_and_wait(chan, "vm-for");
03225 if (d)
03226 return d;
03227 snprintf(fn, sizeof(fn), "vm-%s", mbox(x));
03228 d = vm_play_folder_name(chan, fn);
03229 if (d)
03230 return d;
03231 d = ast_waitfordigit(chan, 500);
03232 if (d)
03233 return d;
03234 }
03235 d = ast_play_and_wait(chan, "vm-tocancel");
03236 if (d)
03237 return d;
03238 d = ast_waitfordigit(chan, 4000);
03239 return d;
03240 }
03241
03242 static int get_folder2(struct ast_channel *chan, char *fn, int start)
03243 {
03244 int res = 0;
03245 res = ast_play_and_wait(chan, fn);
03246 while (((res < '0') || (res > '9')) &&
03247 (res != '#') && (res >= 0)) {
03248 res = get_folder(chan, 0);
03249 }
03250 return res;
03251 }
03252
03253 static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfts,
03254 char *context, signed char record_gain)
03255 {
03256 int cmd = 0;
03257 int retries = 0;
03258 int duration = 0;
03259 signed char zero_gain = 0;
03260
03261 while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
03262 if (cmd)
03263 retries = 0;
03264 switch (cmd) {
03265 case '1':
03266
03267 {
03268 char file[200];
03269 snprintf(file, sizeof(file), "%s/msg%04d", curdir, curmsg);
03270 if (record_gain)
03271 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
03272 cmd = ast_play_and_prepend(chan, NULL, file, 0, vmfmts, &duration, 1, silencethreshold, maxsilence);
03273 if (record_gain)
03274 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
03275 break;
03276 }
03277 case '2':
03278 cmd = 't';
03279 break;
03280 case '*':
03281 cmd = '*';
03282 break;
03283 default:
03284 cmd = ast_play_and_wait(chan,"vm-forwardoptions");
03285
03286 if (!cmd)
03287 cmd = ast_play_and_wait(chan,"vm-starmain");
03288
03289 if (!cmd)
03290 cmd = ast_waitfordigit(chan,6000);
03291 if (!cmd)
03292 retries++;
03293 if (retries > 3)
03294 cmd = 't';
03295 }
03296 }
03297 if (cmd == 't')
03298 cmd = 0;
03299 return cmd;
03300 }
03301
03302 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
03303 {
03304 char todir[256], fn[256], ext_context[256], *stringp;
03305 int newmsgs = 0, oldmsgs = 0;
03306
03307 make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
03308 make_file(fn, sizeof(fn), todir, msgnum);
03309 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
03310
03311
03312 fmt = ast_strdupa(fmt);
03313 if (fmt) {
03314 stringp = fmt;
03315 strsep(&stringp, "|");
03316
03317 if (!ast_strlen_zero(vmu->email)) {
03318 int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
03319 char *myserveremail = serveremail;
03320 attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
03321 if (!ast_strlen_zero(vmu->serveremail))
03322 myserveremail = vmu->serveremail;
03323 sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, fmt, duration, attach_user_voicemail);
03324 }
03325
03326 if (!ast_strlen_zero(vmu->pager)) {
03327 char *myserveremail = serveremail;
03328 if (!ast_strlen_zero(vmu->serveremail))
03329 myserveremail = vmu->serveremail;
03330 sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu);
03331 }
03332 } else {
03333 ast_log(LOG_ERROR, "Out of memory\n");
03334 }
03335
03336 if (ast_test_flag(vmu, VM_DELETE)) {
03337 DELETE(todir, msgnum, fn);
03338 }
03339
03340
03341 if (ast_app_has_voicemail(ext_context, NULL)) {
03342 ast_app_messagecount(ext_context, &newmsgs, &oldmsgs);
03343 }
03344 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs);
03345 run_externnotify(vmu->context, vmu->mailbox);
03346 return 0;
03347 }
03348
03349 static int forward_message(struct ast_channel *chan, char *context, char *dir, int curmsg, struct ast_vm_user *sender,
03350 char *fmt, int flag, signed char record_gain)
03351 {
03352 char username[70]="";
03353 char sys[256];
03354 char todir[256];
03355 int todircount=0;
03356 int duration;
03357 struct ast_config *mif;
03358 char miffile[256];
03359 char fn[256];
03360 char callerid[512];
03361 char ext_context[256]="";
03362 int res = 0, cmd = 0;
03363 struct ast_vm_user *receiver = NULL, *extensions = NULL, *vmtmp = NULL, *vmfree;
03364 char tmp[256];
03365 char *stringp, *s;
03366 int saved_messages = 0, found = 0;
03367 int valid_extensions = 0;
03368
03369 while (!res && !valid_extensions) {
03370 int use_directory = 0;
03371 if(ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
03372 int done = 0;
03373 int retries = 0;
03374 cmd=0;
03375 while((cmd >= 0) && !done ){
03376 if (cmd)
03377 retries = 0;
03378 switch (cmd) {
03379 case '1':
03380 use_directory = 0;
03381 done = 1;
03382 break;
03383 case '2':
03384 use_directory = 1;
03385 done=1;
03386 break;
03387 case '*':
03388 cmd = 't';
03389 done = 1;
03390 break;
03391 default:
03392
03393 cmd = ast_play_and_wait(chan,"vm-forward");
03394 if (!cmd)
03395 cmd = ast_waitfordigit(chan,3000);
03396 if (!cmd)
03397 retries++;
03398 if (retries > 3)
03399 {
03400 cmd = 't';
03401 done = 1;
03402 }
03403
03404 }
03405 }
03406 if( cmd<0 || cmd=='t' )
03407 break;
03408 }
03409
03410 if (use_directory) {
03411
03412
03413 char old_context[sizeof(chan->context)];
03414 char old_exten[sizeof(chan->exten)];
03415 int old_priority;
03416 struct ast_app* app;
03417
03418
03419 app = pbx_findapp("Directory");
03420 if (app) {
03421
03422 memcpy(old_context, chan->context, sizeof(chan->context));
03423 memcpy(old_exten, chan->exten, sizeof(chan->exten));
03424 old_priority = chan->priority;
03425
03426
03427 res = pbx_exec(chan, app, context ? context : "default", 1);
03428
03429 ast_copy_string(username, chan->exten, sizeof(username));
03430
03431
03432 memcpy(chan->context, old_context, sizeof(chan->context));
03433 memcpy(chan->exten, old_exten, sizeof(chan->exten));
03434 chan->priority = old_priority;
03435
03436 } else {
03437 ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
03438 ast_clear_flag((&globalflags), VM_DIRECFORWARD);
03439 }
03440 } else {
03441
03442 res = ast_streamfile(chan, "vm-extension", chan->language);
03443 if (res)
03444 break;
03445 if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
03446 break;
03447 }
03448
03449
03450 if (ast_strlen_zero(username))
03451 continue;
03452 stringp = username;
03453 s = strsep(&stringp, "*");
03454
03455 valid_extensions = 1;
03456 while (s) {
03457
03458 if ((receiver = find_user(NULL, context, s))) {
03459 if (!extensions)
03460 vmtmp = extensions = receiver;
03461 else {
03462 vmtmp->next = receiver;
03463 vmtmp = receiver;
03464 }
03465 found++;
03466 } else {
03467 valid_extensions = 0;
03468 break;
03469 }
03470 s = strsep(&stringp, "*");
03471 }
03472
03473 if (valid_extensions)
03474 break;
03475
03476 res = ast_play_and_wait(chan, "pbx-invalid");
03477 }
03478
03479 if (!extensions || !valid_extensions)
03480 return res;
03481 vmtmp = extensions;
03482 if (flag==1) {
03483 struct leave_vm_options leave_options;
03484
03485
03486 memset(&leave_options, 0, sizeof(leave_options));
03487 leave_options.record_gain = record_gain;
03488 cmd = leave_voicemail(chan, username, &leave_options);
03489 } else {
03490
03491 RETRIEVE(dir, curmsg);
03492 cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, context, record_gain);
03493 if (!cmd) {
03494 while (!res && vmtmp) {
03495
03496
03497
03498 snprintf(todir, sizeof(todir), "%s%s/%s/INBOX", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
03499 snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
03500 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmtmp->mailbox, vmtmp->context);
03501 ast_log(LOG_DEBUG, "%s", sys);
03502 ast_safe_system(sys);
03503
03504 res = count_messages(receiver, todir);
03505
03506 if ( (res == ERROR_LOCK_PATH) || (res < 0) ) {
03507 if (res == ERROR_LOCK_PATH)
03508 ast_log(LOG_WARNING, "Unable to lock the directory %s to forward the requested vmail msg!\n", todir);
03509 else
03510 ast_log(LOG_WARNING, "Unable to determine how many msgs are in the destination folder!\n");
03511 break;
03512 }
03513 todircount = res;
03514 ast_copy_string(tmp, fmt, sizeof(tmp));
03515 stringp = tmp;
03516 while ((s = strsep(&stringp, "|"))) {
03517
03518 if (!strcasecmp(s, "wav49"))
03519 s = "WAV";
03520 snprintf(sys, sizeof(sys), "cp %s/msg%04d.%s %s/msg%04d.%s\n", dir, curmsg, s, todir, todircount, s);
03521 ast_log(LOG_DEBUG, "%s", sys);
03522 ast_safe_system(sys);
03523 }
03524 snprintf(sys, sizeof(sys), "cp %s/msg%04d.txt %s/msg%04d.txt\n", dir, curmsg, todir, todircount);
03525 ast_log(LOG_DEBUG, "%s", sys);
03526 ast_safe_system(sys);
03527 snprintf(fn, sizeof(fn), "%s/msg%04d", todir,todircount);
03528
03529 STORE(todir, vmtmp->mailbox, vmtmp->context, todircount);
03530
03531
03532 snprintf(miffile, sizeof(miffile), "%s/msg%04d.txt", dir, curmsg);
03533 if ((mif=ast_config_load(miffile))) {
03534
03535
03536 snprintf(callerid, sizeof(callerid), "FWD from: %s from %s", sender->fullname, ast_variable_retrieve(mif, NULL, "callerid"));
03537 s = ast_variable_retrieve(mif, NULL, "duration");
03538 if (s)
03539 duration = atoi(s);
03540 else
03541 duration = 0;
03542 if (!ast_strlen_zero(vmtmp->email)) {
03543 int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
03544 char *myserveremail = serveremail;
03545 attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
03546 if (!ast_strlen_zero(vmtmp->serveremail))
03547 myserveremail = vmtmp->serveremail;
03548 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, chan->cid.cid_num, chan->cid.cid_name, fn, tmp, duration, attach_user_voicemail);
03549 }
03550
03551 if (!ast_strlen_zero(vmtmp->pager)) {
03552 char *myserveremail = serveremail;
03553 if (!ast_strlen_zero(vmtmp->serveremail))
03554 myserveremail = vmtmp->serveremail;
03555 sendpage(myserveremail, vmtmp->pager, todircount, vmtmp->context, vmtmp->mailbox, chan->cid.cid_num, chan->cid.cid_name, duration, vmtmp);
03556 }
03557
03558 ast_config_destroy(mif);
03559 }
03560
03561 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
03562 run_externnotify(vmtmp->context, vmtmp->mailbox);
03563
03564 saved_messages++;
03565 vmfree = vmtmp;
03566 vmtmp = vmtmp->next;
03567 free_user(vmfree);
03568 }
03569 if (saved_messages > 0) {
03570
03571
03572
03573
03574
03575
03576
03577
03578 res = ast_play_and_wait(chan, "vm-msgsaved");
03579 }
03580 }
03581 }
03582 return res ? res : cmd;
03583 }
03584
03585 static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
03586 {
03587 int res;
03588 if ((res = ast_streamfile(chan, file, chan->language)))
03589 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
03590 if (!res)
03591 res = ast_waitstream(chan, AST_DIGIT_ANY);
03592 return res;
03593 }
03594
03595 static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
03596 {
03597 return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms);
03598 }
03599
03600 static int play_message_category(struct ast_channel *chan, char *category)
03601 {
03602 int res = 0;
03603
03604 if (!ast_strlen_zero(category))
03605 res = ast_play_and_wait(chan, category);
03606
03607 return res;
03608 }
03609
03610 static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, char *origtime, char *filename)
03611 {
03612 int res = 0;
03613 struct vm_zone *the_zone = NULL;
03614 time_t t;
03615 long tin;
03616
03617 if (sscanf(origtime,"%ld",&tin) < 1) {
03618 ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
03619 return 0;
03620 }
03621 t = tin;
03622
03623
03624 if (!ast_strlen_zero(vmu->zonetag)) {
03625
03626 struct vm_zone *z;
03627 z = zones;
03628 while (z) {
03629 if (!strcmp(z->name, vmu->zonetag)) {
03630 the_zone = z;
03631 break;
03632 }
03633 z = z->next;
03634 }
03635 }
03636
03637
03638 #if 0
03639
03640 localtime_r(&t, &time_now);
03641 tv_now = ast_tvnow();
03642 tnow = tv_now.tv_sec;
03643 localtime_r(&tnow,&time_then);
03644
03645
03646 if (time_now.tm_year == time_then.tm_year)
03647 snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
03648 else
03649 snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
03650 pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
03651
03652
03653 #endif
03654 if (the_zone)
03655 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
03656 else if(!strcasecmp(chan->language,"se"))
03657 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
03658 else if(!strcasecmp(chan->language,"no"))
03659 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
03660 else if(!strcasecmp(chan->language,"de"))
03661 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
03662 else if (!strcasecmp(chan->language,"nl"))
03663 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
03664 else if (!strcasecmp(chan->language,"it"))
03665 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL);
03666 else if (!strcasecmp(chan->language,"gr"))
03667 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
03668 else
03669 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
03670 #if 0
03671 pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
03672 #endif
03673 return res;
03674 }
03675
03676
03677
03678 static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, char *context, int callback)
03679 {
03680 int res = 0;
03681 int i;
03682 char *callerid, *name;
03683 char prefile[256]="";
03684
03685
03686
03687
03688 if ((cid == NULL)||(context == NULL))
03689 return res;
03690
03691
03692 ast_log(LOG_DEBUG, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
03693 ast_callerid_parse(cid, &name, &callerid);
03694 if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
03695
03696
03697 for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
03698 ast_log(LOG_DEBUG, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
03699 if ((strcmp(cidinternalcontexts[i], context) == 0))
03700 break;
03701 }
03702 if (i != MAX_NUM_CID_CONTEXTS){
03703 if (!res) {
03704 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
03705 if (!ast_strlen_zero(prefile)) {
03706
03707 if (ast_fileexists(prefile, NULL, NULL) > 0) {
03708 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
03709 if (!callback)
03710 res = wait_file2(chan, vms, "vm-from");
03711 res = ast_streamfile(chan, prefile, chan->language) > -1;
03712 res = ast_waitstream(chan, "");
03713 } else {
03714 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: message from '%s'\n", callerid);
03715
03716 if (!callback)
03717 res = wait_file2(chan, vms, "vm-from-extension");
03718 res = ast_say_digit_str(chan, callerid, "", chan->language);
03719 }
03720 }
03721 }
03722 }
03723
03724 else if (!res){
03725 ast_log(LOG_DEBUG, "VM-CID: Numeric caller id: (%s)\n",callerid);
03726
03727 if (!callback)
03728 res = wait_file2(chan, vms, "vm-from-phonenumber");
03729 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
03730 }
03731 } else {
03732
03733 ast_log(LOG_DEBUG, "VM-CID: From an unknown number\n");
03734
03735 res = wait_file2(chan, vms, "vm-unknown-caller");
03736 }
03737 return res;
03738 }
03739
03740 static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, char *duration, int minduration)
03741 {
03742 int res = 0;
03743 int durationm;
03744 int durations;
03745
03746 if((duration == NULL))
03747 return res;
03748
03749
03750 durations=atoi(duration);
03751 durationm=(durations / 60);
03752
03753 ast_log(LOG_DEBUG, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
03754
03755 if((!res)&&(durationm>=minduration)) {
03756 res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, (char *) NULL);
03757 res = wait_file2(chan, vms, "vm-minutes");
03758 }
03759 return res;
03760 }
03761
03762 static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
03763 {
03764 int res = 0;
03765 char filename[256],*origtime, *cid, *context, *duration;
03766 char *category;
03767 struct ast_config *msg_cfg;
03768
03769 vms->starting = 0;
03770 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
03771 adsi_message(chan, vms);
03772 if (!vms->curmsg)
03773 res = wait_file2(chan, vms, "vm-first");
03774 else if (vms->curmsg == vms->lastmsg)
03775 res = wait_file2(chan, vms, "vm-last");
03776 if (!res) {
03777 if (!strcasecmp(chan->language, "se")) {
03778 res = wait_file2(chan, vms, "vm-meddelandet");
03779 }
03780 else {
03781 res = wait_file2(chan, vms, "vm-message");
03782 }
03783 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
03784 if (!res)
03785 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
03786 }
03787 }
03788
03789
03790 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
03791 snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
03792 RETRIEVE(vms->curdir, vms->curmsg);
03793 msg_cfg = ast_config_load(filename);
03794 if (!msg_cfg) {
03795 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
03796 return 0;
03797 }
03798
03799 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
03800 ast_log(LOG_WARNING, "No origtime?!\n");
03801 DISPOSE(vms->curdir, vms->curmsg);
03802 ast_config_destroy(msg_cfg);
03803 return 0;
03804 }
03805
03806 cid = ast_variable_retrieve(msg_cfg, "message", "callerid");
03807 duration = ast_variable_retrieve(msg_cfg, "message", "duration");
03808 category = ast_variable_retrieve(msg_cfg, "message", "category");
03809
03810 context = ast_variable_retrieve(msg_cfg, "message", "context");
03811 if (!strncasecmp("macro",context,5))
03812 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
03813
03814 if (!res)
03815 res = play_message_category(chan, category);
03816 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
03817 res = play_message_datetime(chan, vmu, origtime, filename);
03818 if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
03819 res = play_message_callerid(chan, vms, cid, context, 0);
03820 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
03821 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
03822
03823 if (res == '1')
03824 res = 0;
03825 ast_config_destroy(msg_cfg);
03826
03827 if (!res) {
03828 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
03829 vms->heard[vms->curmsg] = 1;
03830 res = wait_file(chan, vms, vms->fn);
03831 }
03832 DISPOSE(vms->curdir, vms->curmsg);
03833 return res;
03834 }
03835
03836 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box)
03837 {
03838 int res = 0;
03839 int count_msg, last_msg;
03840
03841 ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
03842
03843
03844
03845
03846 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
03847
03848 make_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
03849 count_msg = count_messages(vmu, vms->curdir);
03850 if (count_msg < 0)
03851 return count_msg;
03852 else
03853 vms->lastmsg = count_msg - 1;
03854
03855
03856
03857
03858
03859
03860
03861
03862 last_msg = last_message_index(vmu, vms->curdir);
03863 if (last_msg < 0)
03864 return last_msg;
03865 else if(vms->lastmsg != last_msg)
03866 {
03867 ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir);
03868 res = resequence_mailbox(vmu, vms->curdir);
03869 if (res)
03870 return res;
03871 }
03872
03873 return 0;
03874 }
03875
03876 static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
03877 {
03878 int x, nummsg;
03879 int res = 0;
03880
03881 if (vms->lastmsg <= -1)
03882 goto done;
03883
03884
03885 if (vm_lock_path(vms->curdir))
03886 return ERROR_LOCK_PATH;
03887
03888 vms->curmsg = -1;
03889 for (x=0;x < vmu->maxmsg;x++) {
03890 if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) {
03891
03892 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
03893 if (!EXISTS(vms->curdir, x, vms->fn, NULL))
03894 break;
03895 vms->curmsg++;
03896 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
03897 if (strcmp(vms->fn, vms->fn2)) {
03898 RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
03899 }
03900 } else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) {
03901
03902 res = save_to_folder(vmu, vms->curdir, x, vmu->context, vms->username, 1);
03903 if (res == ERROR_LOCK_PATH) {
03904
03905 vms->deleted[x] = 0;
03906 vms->heard[x] = 0;
03907 --x;
03908 }
03909 }
03910 }
03911
03912
03913 nummsg = x - 1;
03914 for (x = vms->curmsg + 1; x <= nummsg; x++) {
03915 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
03916 if (EXISTS(vms->curdir, x, vms->fn, NULL))
03917 DELETE(vms->curdir, x, vms->fn);
03918 }
03919 ast_unlock_path(vms->curdir);
03920
03921 done:
03922 if (vms->deleted)
03923 memset(vms->deleted, 0, sizeof(vms->deleted));
03924 if (vms->heard)
03925 memset(vms->heard, 0, sizeof(vms->heard));
03926
03927 return 0;
03928 }
03929
03930
03931
03932
03933
03934
03935
03936 static int vm_play_folder_name_gr(struct ast_channel *chan, char *mbox)
03937 {
03938 int cmd;
03939 char *buf;
03940
03941 buf = alloca(strlen(mbox)+2);
03942 strcpy(buf, mbox);
03943 strcat(buf,"s");
03944
03945 if (!strcasecmp(mbox, "vm-INBOX") || !strcasecmp(mbox, "vm-Old")){
03946 cmd = ast_play_and_wait(chan, buf);
03947 if (cmd)
03948 return cmd;
03949 return ast_play_and_wait(chan, "vm-messages");
03950 } else {
03951 cmd = ast_play_and_wait(chan, "vm-messages");
03952 if (cmd)
03953 return cmd;
03954 return ast_play_and_wait(chan, mbox);
03955 }
03956 }
03957
03958 static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
03959 {
03960 int cmd;
03961
03962 if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "fr") || !strcasecmp(chan->language, "pt")) {
03963 cmd = ast_play_and_wait(chan, "vm-messages");
03964 if (cmd)
03965 return cmd;
03966 return ast_play_and_wait(chan, mbox);
03967 } else if (!strcasecmp(chan->language, "gr")){
03968 return vm_play_folder_name_gr(chan, mbox);
03969 } else {
03970 cmd = ast_play_and_wait(chan, mbox);
03971 if (cmd)
03972 return cmd;
03973 return ast_play_and_wait(chan, "vm-messages");
03974 }
03975 }
03976
03977
03978
03979
03980
03981
03982
03983
03984
03985
03986
03987
03988
03989 static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
03990 {
03991 int res = 0;
03992
03993 if (vms->newmessages) {
03994 res = ast_play_and_wait(chan, "vm-youhave");
03995 if (!res)
03996 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
03997 if (!res) {
03998 if ((vms->newmessages == 1)) {
03999 res = ast_play_and_wait(chan, "vm-INBOX");
04000 if (!res)
04001 res = ast_play_and_wait(chan, "vm-message");
04002 } else {
04003 res = ast_play_and_wait(chan, "vm-INBOXs");
04004 if (!res)
04005 res = ast_play_and_wait(chan, "vm-messages");
04006 }
04007 }
04008 } else if (vms->oldmessages){
04009 res = ast_play_and_wait(chan, "vm-youhave");
04010 if (!res)
04011 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
04012 if ((vms->oldmessages == 1)){
04013 res = ast_play_and_wait(chan, "vm-Old");
04014 if (!res)
04015 res = ast_play_and_wait(chan, "vm-message");
04016 } else {
04017 res = ast_play_and_wait(chan, "vm-Olds");
04018 if (!res)
04019 res = ast_play_and_wait(chan, "vm-messages");
04020 }
04021 } else if (!vms->oldmessages && !vms->newmessages)
04022 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
04023 return res;
04024 }
04025
04026
04027 static int vm_intro_en(struct ast_channel *chan,struct vm_state *vms)
04028 {
04029
04030 int res;
04031 res = ast_play_and_wait(chan, "vm-youhave");
04032 if (!res) {
04033 if (vms->newmessages) {
04034 res = say_and_wait(chan, vms->newmessages, chan->language);
04035 if (!res)
04036 res = ast_play_and_wait(chan, "vm-INBOX");
04037 if (vms->oldmessages && !res)
04038 res = ast_play_and_wait(chan, "vm-and");
04039 else if (!res) {
04040 if ((vms->newmessages == 1))
04041 res = ast_play_and_wait(chan, "vm-message");
04042 else
04043 res = ast_play_and_wait(chan, "vm-messages");
04044 }
04045
04046 }
04047 if (!res && vms->oldmessages) {
04048 res = say_and_wait(chan, vms->oldmessages, chan->language);
04049 if (!res)
04050 res = ast_play_and_wait(chan, "vm-Old");
04051 if (!res) {
04052 if (vms->oldmessages == 1)
04053 res = ast_play_and_wait(chan, "vm-message");
04054 else
04055 res = ast_play_and_wait(chan, "vm-messages");
04056 }
04057 }
04058 if (!res) {
04059 if (!vms->oldmessages && !vms->newmessages) {
04060 res = ast_play_and_wait(chan, "vm-no");
04061 if (!res)
04062 res = ast_play_and_wait(chan, "vm-messages");
04063 }
04064 }
04065 }
04066 return res;
04067 }
04068
04069
04070 static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
04071 {
04072
04073 int res;
04074 if (!vms->oldmessages && !vms->newmessages)
04075 res = ast_play_and_wait(chan, "vm-no") ||
04076 ast_play_and_wait(chan, "vm-message");
04077 else
04078 res = ast_play_and_wait(chan, "vm-youhave");
04079 if (!res && vms->newmessages) {
04080 res = (vms->newmessages == 1) ?
04081 ast_play_and_wait(chan, "digits/un") ||
04082 ast_play_and_wait(chan, "vm-nuovo") ||
04083 ast_play_and_wait(chan, "vm-message") :
04084
04085 say_and_wait(chan, vms->newmessages, chan->language) ||
04086 ast_play_and_wait(chan, "vm-nuovi") ||
04087 ast_play_and_wait(chan, "vm-messages");
04088 if (!res && vms->oldmessages)
04089 res = ast_play_and_wait(chan, "vm-and");
04090 }
04091 if (!res && vms->oldmessages) {
04092 res = (vms->oldmessages == 1) ?
04093 ast_play_and_wait(chan, "digits/un") ||
04094 ast_play_and_wait(chan, "vm-vecchio") ||
04095 ast_play_and_wait(chan, "vm-message") :
04096
04097 say_and_wait(chan, vms->oldmessages, chan->language) ||
04098 ast_play_and_wait(chan, "vm-vecchi") ||
04099 ast_play_and_wait(chan, "vm-messages");
04100 }
04101 return res ? -1 : 0;
04102 }
04103
04104
04105 static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
04106 {
04107
04108 int res;
04109
04110 res = ast_play_and_wait(chan, "vm-youhave");
04111 if (res)
04112 return res;
04113
04114 if (!vms->oldmessages && !vms->newmessages) {
04115 res = ast_play_and_wait(chan, "vm-no");
04116 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04117 return res;
04118 }
04119
04120 if (vms->newmessages) {
04121 if ((vms->newmessages == 1)) {
04122 res = ast_play_and_wait(chan, "digits/ett");
04123 res = res ? res : ast_play_and_wait(chan, "vm-nytt");
04124 res = res ? res : ast_play_and_wait(chan, "vm-message");
04125 } else {
04126 res = say_and_wait(chan, vms->newmessages, chan->language);
04127 res = res ? res : ast_play_and_wait(chan, "vm-nya");
04128 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04129 }
04130 if (!res && vms->oldmessages)
04131 res = ast_play_and_wait(chan, "vm-and");
04132 }
04133 if (!res && vms->oldmessages) {
04134 if (vms->oldmessages == 1) {
04135 res = ast_play_and_wait(chan, "digits/ett");
04136 res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
04137 res = res ? res : ast_play_and_wait(chan, "vm-message");
04138 } else {
04139 res = say_and_wait(chan, vms->oldmessages, chan->language);
04140 res = res ? res : ast_play_and_wait(chan, "vm-gamla");
04141 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04142 }
04143 }
04144
04145 return res;
04146 }
04147
04148
04149 static int vm_intro_no(struct ast_channel *chan,struct vm_state *vms)
04150 {
04151
04152 int res;
04153
04154 res = ast_play_and_wait(chan, "vm-youhave");
04155 if (res)
04156 return res;
04157
04158 if (!vms->oldmessages && !vms->newmessages) {
04159 res = ast_play_and_wait(chan, "vm-no");
04160 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04161 return res;
04162 }
04163
04164 if (vms->newmessages) {
04165 if ((vms->newmessages == 1)) {
04166 res = ast_play_and_wait(chan, "digits/1");
04167 res = res ? res : ast_play_and_wait(chan, "vm-ny");
04168 res = res ? res : ast_play_and_wait(chan, "vm-message");
04169 } else {
04170 res = say_and_wait(chan, vms->newmessages, chan->language);
04171 res = res ? res : ast_play_and_wait(chan, "vm-nye");
04172 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04173 }
04174 if (!res && vms->oldmessages)
04175 res = ast_play_and_wait(chan, "vm-and");
04176 }
04177 if (!res && vms->oldmessages) {
04178 if (vms->oldmessages == 1) {
04179 res = ast_play_and_wait(chan, "digits/1");
04180 res = res ? res : ast_play_and_wait(chan, "vm-gamel");
04181 res = res ? res : ast_play_and_wait(chan, "vm-message");
04182 } else {
04183 res = say_and_wait(chan, vms->oldmessages, chan->language);
04184 res = res ? res : ast_play_and_wait(chan, "vm-gamle");
04185 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04186 }
04187 }
04188
04189 return res;
04190 }
04191
04192
04193 static int vm_intro_de(struct ast_channel *chan,struct vm_state *vms)
04194 {
04195
04196 int res;
04197 res = ast_play_and_wait(chan, "vm-youhave");
04198 if (!res) {
04199 if (vms->newmessages) {
04200 if ((vms->newmessages == 1))
04201 res = ast_play_and_wait(chan, "digits/1F");
04202 else
04203 res = say_and_wait(chan, vms->newmessages, chan->language);
04204 if (!res)
04205 res = ast_play_and_wait(chan, "vm-INBOX");
04206 if (vms->oldmessages && !res)
04207 res = ast_play_and_wait(chan, "vm-and");
04208 else if (!res) {
04209 if ((vms->newmessages == 1))
04210 res = ast_play_and_wait(chan, "vm-message");
04211 else
04212 res = ast_play_and_wait(chan, "vm-messages");
04213 }
04214
04215 }
04216 if (!res && vms->oldmessages) {
04217 if (vms->oldmessages == 1)
04218 res = ast_play_and_wait(chan, "digits/1F");
04219 else
04220 res = say_and_wait(chan, vms->oldmessages, chan->language);
04221 if (!res)
04222 res = ast_play_and_wait(chan, "vm-Old");
04223 if (!res) {
04224 if (vms->oldmessages == 1)
04225 res = ast_play_and_wait(chan, "vm-message");
04226 else
04227 res = ast_play_and_wait(chan, "vm-messages");
04228 }
04229 }
04230 if (!res) {
04231 if (!vms->oldmessages && !vms->newmessages) {
04232 res = ast_play_and_wait(chan, "vm-no");
04233 if (!res)
04234 res = ast_play_and_wait(chan, "vm-messages");
04235 }
04236 }
04237 }
04238 return res;
04239 }
04240
04241
04242 static int vm_intro_es(struct ast_channel *chan,struct vm_state *vms)
04243 {
04244
04245 int res;
04246 if (!vms->oldmessages && !vms->newmessages) {
04247 res = ast_play_and_wait(chan, "vm-youhaveno");
04248 if (!res)
04249 res = ast_play_and_wait(chan, "vm-messages");
04250 } else {
04251 res = ast_play_and_wait(chan, "vm-youhave");
04252 }
04253 if (!res) {
04254 if (vms->newmessages) {
04255 if (!res) {
04256 if ((vms->newmessages == 1)) {
04257 res = ast_play_and_wait(chan, "digits/1M");
04258 if (!res)
04259 res = ast_play_and_wait(chan, "vm-message");
04260 if (!res)
04261 res = ast_play_and_wait(chan, "vm-INBOXs");
04262 } else {
04263 res = say_and_wait(chan, vms->newmessages, chan->language);
04264 if (!res)
04265 res = ast_play_and_wait(chan, "vm-messages");
04266 if (!res)
04267 res = ast_play_and_wait(chan, "vm-INBOX");
04268 }
04269 }
04270 if (vms->oldmessages && !res)
04271 res = ast_play_and_wait(chan, "vm-and");
04272 }
04273 if (vms->oldmessages) {
04274 if (!res) {
04275 if (vms->oldmessages == 1) {
04276 res = ast_play_and_wait(chan, "digits/1M");
04277 if (!res)
04278 res = ast_play_and_wait(chan, "vm-message");
04279 if (!res)
04280 res = ast_play_and_wait(chan, "vm-Olds");
04281 } else {
04282 res = say_and_wait(chan, vms->oldmessages, chan->language);
04283 if (!res)
04284 res = ast_play_and_wait(chan, "vm-messages");
04285 if (!res)
04286 res = ast_play_and_wait(chan, "vm-Old");
04287 }
04288 }
04289 }
04290 }
04291 return res;
04292 }
04293
04294
04295 static int vm_intro_fr(struct ast_channel *chan,struct vm_state *vms)
04296 {
04297
04298 int res;
04299 res = ast_play_and_wait(chan, "vm-youhave");
04300 if (!res) {
04301 if (vms->newmessages) {
04302 res = say_and_wait(chan, vms->newmessages, chan->language);
04303 if (!res)
04304 res = ast_play_and_wait(chan, "vm-INBOX");
04305 if (vms->oldmessages && !res)
04306 res = ast_play_and_wait(chan, "vm-and");
04307 else if (!res) {
04308 if ((vms->newmessages == 1))
04309 res = ast_play_and_wait(chan, "vm-message");
04310 else
04311 res = ast_play_and_wait(chan, "vm-messages");
04312 }
04313
04314 }
04315 if (!res && vms->oldmessages) {
04316 res = say_and_wait(chan, vms->oldmessages, chan->language);
04317 if (!res) {
04318 if (vms->oldmessages == 1)
04319 res = ast_play_and_wait(chan, "vm-message");
04320 else
04321 res = ast_play_and_wait(chan, "vm-messages");
04322 }
04323 if (!res)
04324 res = ast_play_and_wait(chan, "vm-Old");
04325 }
04326 if (!res) {
04327 if (!vms->oldmessages && !vms->newmessages) {
04328 res = ast_play_and_wait(chan, "vm-no");
04329 if (!res)
04330 res = ast_play_and_wait(chan, "vm-messages");
04331 }
04332 }
04333 }
04334 return res;
04335 }
04336
04337
04338 static int vm_intro_nl(struct ast_channel *chan,struct vm_state *vms)
04339 {
04340
04341 int res;
04342 res = ast_play_and_wait(chan, "vm-youhave");
04343 if (!res) {
04344 if (vms->newmessages) {
04345 res = say_and_wait(chan, vms->newmessages, chan->language);
04346 if (!res) {
04347 if (vms->oldmessages == 1)
04348 res = ast_play_and_wait(chan, "vm-INBOXs");
04349 else
04350 res = ast_play_and_wait(chan, "vm-INBOX");
04351 }
04352 if (vms->oldmessages && !res)
04353 res = ast_play_and_wait(chan, "vm-and");
04354 else if (!res) {
04355 if ((vms->newmessages == 1))
04356 res = ast_play_and_wait(chan, "vm-message");
04357 else
04358 res = ast_play_and_wait(chan, "vm-messages");
04359 }
04360
04361 }
04362 if (!res && vms->oldmessages) {
04363 res = say_and_wait(chan, vms->oldmessages, chan->language);
04364 if (!res) {
04365 if (vms->oldmessages == 1)
04366 res = ast_play_and_wait(chan, "vm-Olds");
04367 else
04368 res = ast_play_and_wait(chan, "vm-Old");
04369 }
04370 if (!res) {
04371 if (vms->oldmessages == 1)
04372 res = ast_play_and_wait(chan, "vm-message");
04373 else
04374 res = ast_play_and_wait(chan, "vm-messages");
04375 }
04376 }
04377 if (!res) {
04378 if (!vms->oldmessages && !vms->newmessages) {
04379 res = ast_play_and_wait(chan, "vm-no");
04380 if (!res)
04381 res = ast_play_and_wait(chan, "vm-messages");
04382 }
04383 }
04384 }
04385 return res;
04386 }
04387
04388
04389 static int vm_intro_pt(struct ast_channel *chan,struct vm_state *vms)
04390 {
04391
04392 int res;
04393 res = ast_play_and_wait(chan, "vm-youhave");
04394 if (!res) {
04395 if (vms->newmessages) {
04396 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
04397 if (!res) {
04398 if ((vms->newmessages == 1)) {
04399 res = ast_play_and_wait(chan, "vm-message");
04400 if (!res)
04401 res = ast_play_and_wait(chan, "vm-INBOXs");
04402 } else {
04403 res = ast_play_and_wait(chan, "vm-messages");
04404 if (!res)
04405 res = ast_play_and_wait(chan, "vm-INBOX");
04406 }
04407 }
04408 if (vms->oldmessages && !res)
04409 res = ast_play_and_wait(chan, "vm-and");
04410 }
04411 if (!res && vms->oldmessages) {
04412 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
04413 if (!res) {
04414 if (vms->oldmessages == 1) {
04415 res = ast_play_and_wait(chan, "vm-message");
04416 if (!res)
04417 res = ast_play_and_wait(chan, "vm-Olds");
04418 } else {
04419 res = ast_play_and_wait(chan, "vm-messages");
04420 if (!res)
04421 res = ast_play_and_wait(chan, "vm-Old");
04422 }
04423 }
04424 }
04425 if (!res) {
04426 if (!vms->oldmessages && !vms->newmessages) {
04427 res = ast_play_and_wait(chan, "vm-no");
04428 if (!res)
04429 res = ast_play_and_wait(chan, "vm-messages");
04430 }
04431 }
04432 }
04433 return res;
04434 }
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452 static int vm_intro_cz(struct ast_channel *chan,struct vm_state *vms)
04453 {
04454 int res;
04455 res = ast_play_and_wait(chan, "vm-youhave");
04456 if (!res) {
04457 if (vms->newmessages) {
04458 if (vms->newmessages == 1) {
04459 res = ast_play_and_wait(chan, "digits/jednu");
04460 } else {
04461 res = say_and_wait(chan, vms->newmessages, chan->language);
04462 }
04463 if (!res) {
04464 if ((vms->newmessages == 1))
04465 res = ast_play_and_wait(chan, "vm-novou");
04466 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
04467 res = ast_play_and_wait(chan, "vm-nove");
04468 if (vms->newmessages > 4)
04469 res = ast_play_and_wait(chan, "vm-novych");
04470 }
04471 if (vms->oldmessages && !res)
04472 res = ast_play_and_wait(chan, "vm-and");
04473 else if (!res) {
04474 if ((vms->newmessages == 1))
04475 res = ast_play_and_wait(chan, "vm-zpravu");
04476 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
04477 res = ast_play_and_wait(chan, "vm-zpravy");
04478 if (vms->newmessages > 4)
04479 res = ast_play_and_wait(chan, "vm-zprav");
04480 }
04481 }
04482 if (!res && vms->oldmessages) {
04483 res = say_and_wait(chan, vms->oldmessages, chan->language);
04484 if (!res) {
04485 if ((vms->oldmessages == 1))
04486 res = ast_play_and_wait(chan, "vm-starou");
04487 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
04488 res = ast_play_and_wait(chan, "vm-stare");
04489 if (vms->oldmessages > 4)
04490 res = ast_play_and_wait(chan, "vm-starych");
04491 }
04492 if (!res) {
04493 if ((vms->oldmessages == 1))
04494 res = ast_play_and_wait(chan, "vm-zpravu");
04495 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
04496 res = ast_play_and_wait(chan, "vm-zpravy");
04497 if (vms->oldmessages > 4)
04498 res = ast_play_and_wait(chan, "vm-zprav");
04499 }
04500 }
04501 if (!res) {
04502 if (!vms->oldmessages && !vms->newmessages) {
04503 res = ast_play_and_wait(chan, "vm-no");
04504 if (!res)
04505 res = ast_play_and_wait(chan, "vm-zpravy");
04506 }
04507 }
04508 }
04509 return res;
04510 }
04511
04512 static int vm_intro(struct ast_channel *chan,struct vm_state *vms)
04513 {
04514
04515 if (!strcasecmp(chan->language, "de")) {
04516 return vm_intro_de(chan, vms);
04517 } else if (!strcasecmp(chan->language, "es")) {
04518 return vm_intro_es(chan, vms);
04519 } else if (!strcasecmp(chan->language, "it")) {
04520 return vm_intro_it(chan, vms);
04521 } else if (!strcasecmp(chan->language, "fr")) {
04522 return vm_intro_fr(chan, vms);
04523 } else if (!strcasecmp(chan->language, "nl")) {
04524 return vm_intro_nl(chan, vms);
04525 } else if (!strcasecmp(chan->language, "pt")) {
04526 return vm_intro_pt(chan, vms);
04527 } else if (!strcasecmp(chan->language, "cz")) {
04528 return vm_intro_cz(chan, vms);
04529 } else if (!strcasecmp(chan->language, "gr")) {
04530 return vm_intro_gr(chan, vms);
04531 } else if (!strcasecmp(chan->language, "se")) {
04532 return vm_intro_se(chan, vms);
04533 } else if (!strcasecmp(chan->language, "no")) {
04534 return vm_intro_no(chan, vms);
04535 } else {
04536 return vm_intro_en(chan, vms);
04537 }
04538 }
04539
04540 static int vm_instructions(struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
04541 {
04542 int res = 0;
04543
04544 while (!res) {
04545 if (vms->starting) {
04546 if (vms->lastmsg > -1) {
04547 res = ast_play_and_wait(chan, "vm-onefor");
04548 if (!res)
04549 res = vm_play_folder_name(chan, vms->vmbox);
04550 }
04551 if (!res)
04552 res = ast_play_and_wait(chan, "vm-opts");
04553 } else {
04554 if (vms->curmsg)
04555 res = ast_play_and_wait(chan, "vm-prev");
04556 if (!res && !skipadvanced)
04557 res = ast_play_and_wait(chan, "vm-advopts");
04558 if (!res)
04559 res = ast_play_and_wait(chan, "vm-repeat");
04560 if (!res && (vms->curmsg != vms->lastmsg))
04561 res = ast_play_and_wait(chan, "vm-next");
04562 if (!res) {
04563 if (!vms->deleted[vms->curmsg])
04564 res = ast_play_and_wait(chan, "vm-delete");
04565 else
04566 res = ast_play_and_wait(chan, "vm-undelete");
04567 if (!res)
04568 res = ast_play_and_wait(chan, "vm-toforward");
04569 if (!res)
04570 res = ast_play_and_wait(chan, "vm-savemessage");
04571 }
04572 }
04573 if (!res)
04574 res = ast_play_and_wait(chan, "vm-helpexit");
04575 if (!res)
04576 res = ast_waitfordigit(chan, 6000);
04577 if (!res) {
04578 vms->repeats++;
04579 if (vms->repeats > 2) {
04580 res = 't';
04581 }
04582 }
04583 }
04584 return res;
04585 }
04586
04587 static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04588 {
04589 int cmd = 0;
04590 int duration = 0;
04591 int tries = 0;
04592 char newpassword[80] = "";
04593 char newpassword2[80] = "";
04594 char prefile[256]="";
04595 unsigned char buf[256];
04596 int bytes=0;
04597
04598 if (adsi_available(chan)) {
04599 bytes += adsi_logo(buf + bytes);
04600 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
04601 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04602 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04603 bytes += adsi_voice_mode(buf + bytes, 0);
04604 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04605 }
04606
04607
04608
04609 for (;;) {
04610 newpassword[1] = '\0';
04611 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
04612 if (cmd == '#')
04613 newpassword[0] = '\0';
04614 if (cmd < 0 || cmd == 't' || cmd == '#')
04615 return cmd;
04616 cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
04617 if (cmd < 0 || cmd == 't' || cmd == '#')
04618 return cmd;
04619 newpassword2[1] = '\0';
04620 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
04621 if (cmd == '#')
04622 newpassword2[0] = '\0';
04623 if (cmd < 0 || cmd == 't' || cmd == '#')
04624 return cmd;
04625 cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#");
04626 if (cmd < 0 || cmd == 't' || cmd == '#')
04627 return cmd;
04628 if (!strcmp(newpassword, newpassword2))
04629 break;
04630 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
04631 cmd = ast_play_and_wait(chan, "vm-mismatch");
04632 if (++tries == 3)
04633 return -1;
04634 }
04635 if (ast_strlen_zero(ext_pass_cmd))
04636 vm_change_password(vmu,newpassword);
04637 else
04638 vm_change_password_shell(vmu,newpassword);
04639
04640 cmd = ast_play_and_wait(chan,"vm-passchanged");
04641
04642
04643 if (ast_test_flag(vmu, VM_FORCENAME)) {
04644 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
04645 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04646 if (cmd < 0 || cmd == 't' || cmd == '#')
04647 return cmd;
04648 }
04649
04650
04651 if (ast_test_flag(vmu, VM_FORCEGREET)) {
04652 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
04653 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04654 if (cmd < 0 || cmd == 't' || cmd == '#')
04655 return cmd;
04656 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
04657 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04658 if (cmd < 0 || cmd == 't' || cmd == '#')
04659 return cmd;
04660 }
04661
04662 return cmd;
04663 }
04664
04665 static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04666 {
04667 int cmd = 0;
04668 int retries = 0;
04669 int duration = 0;
04670 char newpassword[80] = "";
04671 char newpassword2[80] = "";
04672 char prefile[256]="";
04673 unsigned char buf[256];
04674 int bytes=0;
04675
04676 if (adsi_available(chan))
04677 {
04678 bytes += adsi_logo(buf + bytes);
04679 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
04680 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04681 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04682 bytes += adsi_voice_mode(buf + bytes, 0);
04683 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04684 }
04685 while ((cmd >= 0) && (cmd != 't')) {
04686 if (cmd)
04687 retries = 0;
04688 switch (cmd) {
04689 case '1':
04690 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
04691 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04692 break;
04693 case '2':
04694 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
04695 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04696 break;
04697 case '3':
04698 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
04699 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04700 break;
04701 case '4':
04702 cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
04703 break;
04704 case '5':
04705 if (vmu->password[0] == '-') {
04706 cmd = ast_play_and_wait(chan, "vm-no");
04707 break;
04708 }
04709 newpassword[1] = '\0';
04710 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
04711 if (cmd == '#')
04712 newpassword[0] = '\0';
04713 else {
04714 if (cmd < 0)
04715 break;
04716 if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
04717 break;
04718 }
04719 }
04720 newpassword2[1] = '\0';
04721 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
04722 if (cmd == '#')
04723 newpassword2[0] = '\0';
04724 else {
04725 if (cmd < 0)
04726 break;
04727
04728 if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#"))) {
04729 break;
04730 }
04731 }
04732 if (strcmp(newpassword, newpassword2)) {
04733 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
04734 cmd = ast_play_and_wait(chan, "vm-mismatch");
04735 break;
04736 }
04737 if (ast_strlen_zero(ext_pass_cmd))
04738 vm_change_password(vmu,newpassword);
04739 else
04740 vm_change_password_shell(vmu,newpassword);
04741 ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
04742 cmd = ast_play_and_wait(chan,"vm-passchanged");
04743 break;
04744 case '*':
04745 cmd = 't';
04746 break;
04747 default:
04748 cmd = ast_play_and_wait(chan,"vm-options");
04749 if (!cmd)
04750 cmd = ast_waitfordigit(chan,6000);
04751 if (!cmd)
04752 retries++;
04753 if (retries > 3)
04754 cmd = 't';
04755 }
04756 }
04757 if (cmd == 't')
04758 cmd = 0;
04759 return cmd;
04760 }
04761
04762 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04763 {
04764 int cmd = 0;
04765 int retries = 0;
04766 int duration = 0;
04767 char prefile[256]="";
04768 unsigned char buf[256];
04769 int bytes=0;
04770
04771 if (adsi_available(chan))
04772 {
04773 bytes += adsi_logo(buf + bytes);
04774 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
04775 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04776 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04777 bytes += adsi_voice_mode(buf + bytes, 0);
04778 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04779 }
04780 snprintf(prefile,sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
04781 while((cmd >= 0) && (cmd != 't')) {
04782 if (cmd)
04783 retries = 0;
04784 RETRIEVE(prefile, -1);
04785 if (ast_fileexists(prefile, NULL, NULL) > 0) {
04786 switch (cmd) {
04787 case '1':
04788 cmd = play_record_review(chan,"vm-rec-temp",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04789 break;
04790 case '2':
04791 DELETE(prefile, -1, prefile);
04792 ast_play_and_wait(chan,"vm-tempremoved");
04793 cmd = 't';
04794 break;
04795 case '*':
04796 cmd = 't';
04797 break;
04798 default:
04799 if (ast_fileexists(prefile, NULL, NULL) > 0) {
04800 cmd = ast_play_and_wait(chan,"vm-tempgreeting2");
04801 } else {
04802 cmd = ast_play_and_wait(chan,"vm-tempgreeting");
04803 } if (!cmd) {
04804 cmd = ast_waitfordigit(chan,6000);
04805 } if (!cmd) {
04806 retries++;
04807 } if (retries > 3) {
04808 cmd = 't';
04809 }
04810 }
04811 } else {
04812 play_record_review(chan,"vm-rec-temp",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04813 cmd = 't';
04814 }
04815 DISPOSE(prefile, -1);
04816 }
04817 if (cmd == 't')
04818 cmd = 0;
04819 return cmd;
04820 }
04821
04822
04823
04824 static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04825 {
04826 int cmd=0;
04827
04828 if (vms->lastmsg > -1) {
04829 cmd = play_message(chan, vmu, vms);
04830 } else {
04831 cmd = ast_play_and_wait(chan, "vm-youhaveno");
04832 if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
04833 if (!cmd) {
04834 snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
04835 cmd = ast_play_and_wait(chan, vms->fn);
04836 }
04837 if (!cmd)
04838 cmd = ast_play_and_wait(chan, "vm-messages");
04839 } else {
04840 if (!cmd)
04841 cmd = ast_play_and_wait(chan, "vm-messages");
04842 if (!cmd) {
04843 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04844 cmd = ast_play_and_wait(chan, vms->fn);
04845 }
04846 }
04847 }
04848 return cmd;
04849 }
04850
04851
04852 static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04853 {
04854 int cmd=0;
04855
04856 if (vms->lastmsg > -1) {
04857 cmd = play_message(chan, vmu, vms);
04858 } else {
04859 cmd = ast_play_and_wait(chan, "vm-youhave");
04860 if (!cmd)
04861 cmd = ast_play_and_wait(chan, "vm-no");
04862 if (!cmd) {
04863 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04864 cmd = ast_play_and_wait(chan, vms->fn);
04865 }
04866 if (!cmd)
04867 cmd = ast_play_and_wait(chan, "vm-messages");
04868 }
04869 return cmd;
04870 }
04871
04872
04873 static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04874 {
04875 int cmd=0;
04876
04877 if (vms->lastmsg > -1) {
04878 cmd = play_message(chan, vmu, vms);
04879 } else {
04880 cmd = ast_play_and_wait(chan, "vm-no");
04881 if (!cmd)
04882 cmd = ast_play_and_wait(chan, "vm-message");
04883 if (!cmd) {
04884 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04885 cmd = ast_play_and_wait(chan, vms->fn);
04886 }
04887 }
04888 return cmd;
04889 }
04890
04891
04892 static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04893 {
04894 int cmd=0;
04895
04896 if (vms->lastmsg > -1) {
04897 cmd = play_message(chan, vmu, vms);
04898 } else {
04899 cmd = ast_play_and_wait(chan, "vm-youhaveno");
04900 if (!cmd)
04901 cmd = ast_play_and_wait(chan, "vm-messages");
04902 if (!cmd) {
04903 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04904 cmd = ast_play_and_wait(chan, vms->fn);
04905 }
04906 }
04907 return cmd;
04908 }
04909
04910
04911 static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04912 {
04913 int cmd=0;
04914
04915 if (vms->lastmsg > -1) {
04916 cmd = play_message(chan, vmu, vms);
04917 } else {
04918 cmd = ast_play_and_wait(chan, "vm-no");
04919 if (!cmd) {
04920 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04921 cmd = ast_play_and_wait(chan, vms->fn);
04922 }
04923 if (!cmd)
04924 cmd = ast_play_and_wait(chan, "vm-messages");
04925 }
04926 return cmd;
04927 }
04928
04929 static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04930 {
04931 if (!strcasecmp(chan->language, "es")) {
04932 return vm_browse_messages_es(chan, vms, vmu);
04933 } else if (!strcasecmp(chan->language, "it")) {
04934 return vm_browse_messages_it(chan, vms, vmu);
04935 } else if (!strcasecmp(chan->language, "pt")) {
04936 return vm_browse_messages_pt(chan, vms, vmu);
04937 } else if (!strcasecmp(chan->language, "gr")){
04938 return vm_browse_messages_gr(chan, vms, vmu);
04939 } else {
04940 return vm_browse_messages_en(chan, vms, vmu);
04941 }
04942 }
04943
04944 static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size,
04945 struct ast_vm_user *res_vmu, const char *context, const char *prefix,
04946 int skipuser, int maxlogins, int silent)
04947 {
04948 int useadsi=0, valid=0, logretries=0;
04949 char password[AST_MAX_EXTENSION]="", *passptr;
04950 struct ast_vm_user vmus, *vmu = NULL;
04951
04952
04953 adsi_begin(chan, &useadsi);
04954 if (!skipuser && useadsi)
04955 adsi_login(chan);
04956 if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
04957 ast_log(LOG_WARNING, "Couldn't stream login file\n");
04958 return -1;
04959 }
04960
04961
04962
04963 while (!valid && (logretries < maxlogins)) {
04964
04965 if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
04966 ast_log(LOG_WARNING, "Couldn't read username\n");
04967 return -1;
04968 }
04969 if (ast_strlen_zero(mailbox)) {
04970 if (chan->cid.cid_num) {
04971 ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
04972 } else {
04973 if (option_verbose > 2)
04974 ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
04975 return -1;
04976 }
04977 }
04978 if (useadsi)
04979 adsi_password(chan);
04980
04981 if (!ast_strlen_zero(prefix)) {
04982 char fullusername[80] = "";
04983 ast_copy_string(fullusername, prefix, sizeof(fullusername));
04984 strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
04985 ast_copy_string(mailbox, fullusername, mailbox_size);
04986 }
04987
04988 vmu = find_user(&vmus, context, mailbox);
04989 if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
04990
04991 password[0] = '\0';
04992 } else {
04993 if (ast_streamfile(chan, "vm-password", chan->language)) {
04994 ast_log(LOG_WARNING, "Unable to stream password file\n");
04995 return -1;
04996 }
04997 if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
04998 ast_log(LOG_WARNING, "Unable to read password\n");
04999 return -1;
05000 }
05001 }
05002
05003 if (vmu) {
05004 passptr = vmu->password;
05005 if (passptr[0] == '-') passptr++;
05006 }
05007 if (vmu && !strcmp(passptr, password))
05008 valid++;
05009 else {
05010 if (option_verbose > 2)
05011 ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
05012 if (!ast_strlen_zero(prefix))
05013 mailbox[0] = '\0';
05014 }
05015 logretries++;
05016 if (!valid) {
05017 if (skipuser || logretries >= maxlogins) {
05018 if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
05019 ast_log(LOG_WARNING, "Unable to stream incorrect message\n");
05020 return -1;
05021 }
05022 } else {
05023 if (useadsi)
05024 adsi_login(chan);
05025 if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
05026 ast_log(LOG_WARNING, "Unable to stream incorrect mailbox message\n");
05027 return -1;
05028 }
05029 }
05030 if (ast_waitstream(chan, ""))
05031 return -1;
05032 }
05033 }
05034 if (!valid && (logretries >= maxlogins)) {
05035 ast_stopstream(chan);
05036 ast_play_and_wait(chan, "vm-goodbye");
05037 return -1;
05038 }
05039 if (vmu && !skipuser) {
05040 memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
05041 }
05042 return 0;
05043 }
05044
05045 static int vm_execmain(struct ast_channel *chan, void *data)
05046 {
05047
05048
05049
05050 int res=-1;
05051 int cmd=0;
05052 int valid = 0;
05053 struct localuser *u;
05054 char prefixstr[80] ="";
05055 char ext_context[256]="";
05056 int box;
05057 int useadsi = 0;
05058 int skipuser = 0;
05059 struct vm_state vms;
05060 struct ast_vm_user *vmu = NULL, vmus;
05061 char *context=NULL;
05062 int silentexit = 0;
05063 struct ast_flags flags = { 0 };
05064 signed char record_gain = 0;
05065
05066 LOCAL_USER_ADD(u);
05067
05068 memset(&vms, 0, sizeof(vms));
05069 vms.lastmsg = -1;
05070
05071 memset(&vmus, 0, sizeof(vmus));
05072
05073 if (chan->_state != AST_STATE_UP)
05074 ast_answer(chan);
05075
05076 if (!ast_strlen_zero(data)) {
05077 char *tmp;
05078 int argc;
05079 char *argv[2];
05080 char *opts[OPT_ARG_ARRAY_SIZE];
05081
05082 tmp = ast_strdupa(data);
05083 argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
05084 if (argc == 2) {
05085 if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
05086 LOCAL_USER_REMOVE(u);
05087 return -1;
05088 }
05089 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
05090 int gain;
05091
05092 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
05093 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
05094 LOCAL_USER_REMOVE(u);
05095 return -1;
05096 } else {
05097 record_gain = (signed char) gain;
05098 }
05099 }
05100 } else {
05101
05102 while (*argv[0]) {
05103 if (*argv[0] == 's') {
05104 ast_set_flag(&flags, OPT_SILENT);
05105 argv[0]++;
05106 } else if (*argv[0] == 'p') {
05107 ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
05108 argv[0]++;
05109 } else
05110 break;
05111 }
05112
05113 }
05114
05115 valid = ast_test_flag(&flags, OPT_SILENT);
05116
05117 if ((context = strchr(argv[0], '@')))
05118 *context++ = '\0';
05119
05120 if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
05121 ast_copy_string(prefixstr, argv[0], sizeof(prefixstr));
05122 else
05123 ast_copy_string(vms.username, argv[0], sizeof(vms.username));
05124
05125 if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
05126 skipuser++;
05127 else
05128 valid = 0;
05129 }
05130
05131 if (!valid)
05132 res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
05133
05134 if (!res) {
05135 valid = 1;
05136 if (!skipuser)
05137 vmu = &vmus;
05138 } else {
05139 res = 0;
05140 }
05141
05142
05143 adsi_begin(chan, &useadsi);
05144
05145 if (!valid)
05146 goto out;
05147
05148 vms.deleted = calloc(vmu->maxmsg, sizeof(int));
05149 vms.heard = calloc(vmu->maxmsg, sizeof(int));
05150
05151
05152 if (!ast_strlen_zero(vmu->language))
05153 ast_copy_string(chan->language, vmu->language, sizeof(chan->language));
05154 create_dirpath(vms.curdir, sizeof(vms.curdir), vmu->context, vms.username, "");
05155
05156 res = open_mailbox(&vms, vmu, 1);
05157 if (res == ERROR_LOCK_PATH)
05158 goto out;
05159 vms.oldmessages = vms.lastmsg + 1;
05160
05161 res = open_mailbox(&vms, vmu, 0);
05162 if (res == ERROR_LOCK_PATH)
05163 goto out;
05164 vms.newmessages = vms.lastmsg + 1;
05165
05166
05167 if (!vms.newmessages && vms.oldmessages) {
05168
05169 res = open_mailbox(&vms, vmu, 1);
05170 if (res == ERROR_LOCK_PATH)
05171 goto out;
05172 }
05173
05174 if (useadsi)
05175 adsi_status(chan, &vms);
05176 res = 0;
05177
05178
05179 if (!strcasecmp(vmu->mailbox, vmu->password) &&
05180 (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
05181 if (ast_play_and_wait(chan, "vm-newuser") == -1)
05182 ast_log(LOG_WARNING, "Couldn't stream new user file\n");
05183 cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
05184 if ((cmd == 't') || (cmd == '#')) {
05185
05186 res = 0;
05187 goto out;
05188 } else if (cmd < 0) {
05189
05190 res = -1;
05191 goto out;
05192 }
05193 }
05194
05195 cmd = vm_intro(chan, &vms);
05196
05197 vms.repeats = 0;
05198 vms.starting = 1;
05199 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
05200
05201 switch(cmd) {
05202 case '1':
05203 vms.curmsg = 0;
05204
05205 case '5':
05206 cmd = vm_browse_messages(chan, &vms, vmu);
05207 break;
05208 case '2':
05209 if (useadsi)
05210 adsi_folders(chan, 0, "Change to folder...");
05211 cmd = get_folder2(chan, "vm-changeto", 0);
05212 if (cmd == '#') {
05213 cmd = 0;
05214 } else if (cmd > 0) {
05215 cmd = cmd - '0';
05216 res = close_mailbox(&vms, vmu);
05217 if (res == ERROR_LOCK_PATH)
05218 goto out;
05219 res = open_mailbox(&vms, vmu, cmd);
05220 if (res == ERROR_LOCK_PATH)
05221 goto out;
05222 cmd = 0;
05223 }
05224 if (useadsi)
05225 adsi_status2(chan, &vms);
05226
05227 if (!cmd)
05228 cmd = vm_play_folder_name(chan, vms.vmbox);
05229
05230 vms.starting = 1;
05231 break;
05232 case '3':
05233 cmd = 0;
05234 vms.repeats = 0;
05235 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
05236 switch(cmd) {
05237 case '1':
05238 if (vms.lastmsg > -1) {
05239 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
05240 if (cmd == ERROR_LOCK_PATH) {
05241 res = cmd;
05242 goto out;
05243 }
05244 } else
05245 cmd = ast_play_and_wait(chan, "vm-sorry");
05246 cmd = 't';
05247 break;
05248 case '2':
05249 ast_verbose( VERBOSE_PREFIX_3 "Callback Requested\n");
05250 if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1) {
05251 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
05252 if (cmd == 9) {
05253 silentexit = 1;
05254 goto out;
05255 } else if (cmd == ERROR_LOCK_PATH) {
05256 res = cmd;
05257 goto out;
05258 }
05259 }
05260 else
05261 cmd = ast_play_and_wait(chan, "vm-sorry");
05262 cmd = 't';
05263 break;
05264 case '3':
05265 if (vms.lastmsg > -1) {
05266 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
05267 if (cmd == ERROR_LOCK_PATH) {
05268 res = cmd;
05269 goto out;
05270 }
05271 } else
05272 cmd = ast_play_and_wait(chan, "vm-sorry");
05273 cmd = 't';
05274 break;
05275 case '4':
05276 if (!ast_strlen_zero(vmu->dialout)) {
05277 cmd = dialout(chan, vmu, NULL, vmu->dialout);
05278 if (cmd == 9) {
05279 silentexit = 1;
05280 goto out;
05281 }
05282 }
05283 else
05284 cmd = ast_play_and_wait(chan, "vm-sorry");
05285 cmd = 't';
05286 break;
05287
05288 case '5':
05289 if (ast_test_flag(vmu, VM_SVMAIL)) {
05290 cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts, 1, record_gain);
05291 if (cmd == ERROR_LOCK_PATH) {
05292 res = cmd;
05293 goto out;
05294 }
05295 } else
05296 cmd = ast_play_and_wait(chan,"vm-sorry");
05297 cmd='t';
05298 break;
05299
05300 case '*':
05301 cmd = 't';
05302 break;
05303
05304 default:
05305 cmd = 0;
05306 if (!vms.starting) {
05307 cmd = ast_play_and_wait(chan, "vm-toreply");
05308 }
05309 if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
05310 cmd = ast_play_and_wait(chan, "vm-tocallback");
05311 }
05312 if (!cmd && !vms.starting) {
05313 cmd = ast_play_and_wait(chan, "vm-tohearenv");
05314 }
05315 if (!ast_strlen_zero(vmu->dialout) && !cmd) {
05316 cmd = ast_play_and_wait(chan, "vm-tomakecall");
05317 }
05318 if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
05319 cmd=ast_play_and_wait(chan, "vm-leavemsg");
05320 if (!cmd)
05321 cmd = ast_play_and_wait(chan, "vm-starmain");
05322 if (!cmd)
05323 cmd = ast_waitfordigit(chan,6000);
05324 if (!cmd)
05325 vms.repeats++;
05326 if (vms.repeats > 3)
05327 cmd = 't';
05328 }
05329 }
05330 if (cmd == 't') {
05331 cmd = 0;
05332 vms.repeats = 0;
05333 }
05334 break;
05335 case '4':
05336 if (vms.curmsg) {
05337 vms.curmsg--;
05338 cmd = play_message(chan, vmu, &vms);
05339 } else {
05340 cmd = ast_play_and_wait(chan, "vm-nomore");
05341 }
05342 break;
05343 case '6':
05344 if (vms.curmsg < vms.lastmsg) {
05345 vms.curmsg++;
05346 cmd = play_message(chan, vmu, &vms);
05347 } else {
05348 cmd = ast_play_and_wait(chan, "vm-nomore");
05349 }
05350 break;
05351 case '7':
05352 vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
05353 if (useadsi)
05354 adsi_delete(chan, &vms);
05355 if (vms.deleted[vms.curmsg])
05356 cmd = ast_play_and_wait(chan, "vm-deleted");
05357 else
05358 cmd = ast_play_and_wait(chan, "vm-undeleted");
05359 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
05360 if (vms.curmsg < vms.lastmsg) {
05361 vms.curmsg++;
05362 cmd = play_message(chan, vmu, &vms);
05363 } else {
05364 cmd = ast_play_and_wait(chan, "vm-nomore");
05365 }
05366 }
05367 break;
05368
05369 case '8':
05370 if (vms.lastmsg > -1) {
05371 cmd = forward_message(chan, context, vms.curdir, vms.curmsg, vmu, vmfmts, 0, record_gain);
05372 if (cmd == ERROR_LOCK_PATH) {
05373 res = cmd;
05374 goto out;
05375 }
05376 } else
05377 cmd = ast_play_and_wait(chan, "vm-nomore");
05378 break;
05379 case '9':
05380 if (useadsi)
05381 adsi_folders(chan, 1, "Save to folder...");
05382 cmd = get_folder2(chan, "vm-savefolder", 1);
05383 box = 0;
05384 if (cmd == '#') {
05385 cmd = 0;
05386 break;
05387 } else if (cmd > 0) {
05388 box = cmd = cmd - '0';
05389 cmd = save_to_folder(vmu, vms.curdir, vms.curmsg, vmu->context, vms.username, cmd);
05390 if (cmd == ERROR_LOCK_PATH) {
05391 res = cmd;
05392 goto out;
05393 } else if (!cmd) {
05394 vms.deleted[vms.curmsg] = 1;
05395 } else {
05396 vms.deleted[vms.curmsg] = 0;
05397 vms.heard[vms.curmsg] = 0;
05398 }
05399 }
05400 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
05401 if (useadsi)
05402 adsi_message(chan, &vms);
05403 snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
05404 if (!cmd) {
05405 cmd = ast_play_and_wait(chan, "vm-message");
05406 if (!cmd)
05407 cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
05408 if (!cmd)
05409 cmd = ast_play_and_wait(chan, "vm-savedto");
05410 if (!cmd)
05411 cmd = vm_play_folder_name(chan, vms.fn);
05412 } else {
05413 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
05414 }
05415 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
05416 if (vms.curmsg < vms.lastmsg) {
05417 vms.curmsg++;
05418 cmd = play_message(chan, vmu, &vms);
05419 } else {
05420 cmd = ast_play_and_wait(chan, "vm-nomore");
05421 }
05422 }
05423 break;
05424 case '*':
05425 if (!vms.starting) {
05426 cmd = ast_play_and_wait(chan, "vm-onefor");
05427 if (!cmd)
05428 cmd = vm_play_folder_name(chan, vms.vmbox);
05429 if (!cmd)
05430 cmd = ast_play_and_wait(chan, "vm-opts");
05431 if (!cmd)
05432 cmd = vm_instructions(chan, &vms, 1);
05433 } else
05434 cmd = 0;
05435 break;
05436 case '0':
05437 cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
05438 if (useadsi)
05439 adsi_status(chan, &vms);
05440 break;
05441 default:
05442 cmd = vm_instructions(chan, &vms, 0);
05443 break;
05444 }
05445 }
05446 if ((cmd == 't') || (cmd == '#')) {
05447
05448 res = 0;
05449 } else {
05450
05451 res = -1;
05452 }
05453
05454 out:
05455 if (res > -1) {
05456 ast_stopstream(chan);
05457 adsi_goodbye(chan);
05458 if (valid) {
05459 if (silentexit)
05460 res = ast_play_and_wait(chan, "vm-dialout");
05461 else
05462 res = ast_play_and_wait(chan, "vm-goodbye");
05463 if (res > 0)
05464 res = 0;
05465 }
05466 if (useadsi)
05467 adsi_unload_session(chan);
05468 }
05469 if (vmu)
05470 close_mailbox(&vms, vmu);
05471 if (valid) {
05472 snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
05473 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
05474 run_externnotify(vmu->context, vmu->mailbox);
05475 }
05476 if (vmu)
05477 free_user(vmu);
05478 if (vms.deleted)
05479 free(vms.deleted);
05480 if (vms.heard)
05481 free(vms.heard);
05482 LOCAL_USER_REMOVE(u);
05483
05484 return res;
05485 }
05486
05487 static int vm_exec(struct ast_channel *chan, void *data)
05488 {
05489 int res = 0;
05490 struct localuser *u;
05491 char tmp[256];
05492 struct leave_vm_options leave_options;
05493 int argc;
05494 char *argv[2];
05495 struct ast_flags flags = { 0 };
05496 char *opts[OPT_ARG_ARRAY_SIZE];
05497
05498 LOCAL_USER_ADD(u);
05499
05500 memset(&leave_options, 0, sizeof(leave_options));
05501
05502 if (chan->_state != AST_STATE_UP)
05503 ast_answer(chan);
05504
05505 if (!ast_strlen_zero(data)) {
05506 ast_copy_string(tmp, data, sizeof(tmp));
05507 argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
05508 if (argc == 2) {
05509 if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
05510 LOCAL_USER_REMOVE(u);
05511 return -1;
05512 }
05513 ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING);
05514 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
05515 int gain;
05516
05517 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
05518 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
05519 LOCAL_USER_REMOVE(u);
05520 return -1;
05521 } else {
05522 leave_options.record_gain = (signed char) gain;
05523 }
05524 }
05525 } else {
05526
05527 while (*argv[0]) {
05528 if (*argv[0] == 's') {
05529 ast_set_flag(&leave_options, OPT_SILENT);
05530 argv[0]++;
05531 } else if (*argv[0] == 'b') {
05532 ast_set_flag(&leave_options, OPT_BUSY_GREETING);
05533 argv[0]++;
05534 } else if (*argv[0] == 'u') {
05535 ast_set_flag(&leave_options, OPT_UNAVAIL_GREETING);
05536 argv[0]++;
05537 } else if (*argv[0] == 'j') {
05538 ast_set_flag(&leave_options, OPT_PRIORITY_JUMP);
05539 argv[0]++;
05540 } else
05541 break;
05542 }
05543 }
05544 } else {
05545 res = ast_app_getdata(chan, "vm-whichbox", tmp, sizeof(tmp) - 1, 0);
05546 if (res < 0) {
05547 LOCAL_USER_REMOVE(u);
05548 return res;
05549 }
05550 if (ast_strlen_zero(tmp)) {
05551 LOCAL_USER_REMOVE(u);
05552 return 0;
05553 }
05554 argv[0] = ast_strdupa(tmp);
05555 }
05556
05557 res = leave_voicemail(chan, argv[0], &leave_options);
05558
05559 if (res == ERROR_LOCK_PATH) {
05560 ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
05561
05562 if (ast_test_flag(&leave_options, OPT_PRIORITY_JUMP) || option_priority_jumping)
05563 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
05564 ast_log(LOG_WARNING, "Extension %s, priority %d doesn't exist.\n", chan->exten, chan->priority + 101);
05565 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05566 res = 0;
05567 }
05568
05569 LOCAL_USER_REMOVE(u);
05570
05571 return res;
05572 }
05573
05574 static int append_mailbox(char *context, char *mbox, char *data)
05575 {
05576
05577 char tmp[256] = "";
05578 char *stringp;
05579 char *s;
05580 struct ast_vm_user *vmu;
05581
05582 ast_copy_string(tmp, data, sizeof(tmp));
05583 vmu = malloc(sizeof(struct ast_vm_user));
05584 if (vmu) {
05585 memset(vmu, 0, sizeof(struct ast_vm_user));
05586 ast_copy_string(vmu->context, context, sizeof(vmu->context));
05587 ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
05588
05589 populate_defaults(vmu);
05590
05591 stringp = tmp;
05592 if ((s = strsep(&stringp, ",")))
05593 ast_copy_string(vmu->password, s, sizeof(vmu->password));
05594 if (stringp && (s = strsep(&stringp, ",")))
05595 ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
05596 if (stringp && (s = strsep(&stringp, ",")))
05597 ast_copy_string(vmu->email, s, sizeof(vmu->email));
05598 if (stringp && (s = strsep(&stringp, ",")))
05599 ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
05600 if (stringp && (s = strsep(&stringp, ",")))
05601 apply_options(vmu, s);
05602
05603 vmu->next = NULL;
05604 if (usersl)
05605 usersl->next = vmu;
05606 else
05607 users = vmu;
05608 usersl = vmu;
05609 }
05610 return 0;
05611 }
05612
05613 static int vm_box_exists(struct ast_channel *chan, void *data)
05614 {
05615 struct localuser *u;
05616 struct ast_vm_user svm;
05617 char *context, *box;
05618 int priority_jump = 0;
05619 AST_DECLARE_APP_ARGS(args,
05620 AST_APP_ARG(mbox);
05621 AST_APP_ARG(options);
05622 );
05623
05624 if (ast_strlen_zero(data)) {
05625 ast_log(LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
05626 return -1;
05627 }
05628
05629 LOCAL_USER_ADD(u);
05630
05631 box = ast_strdupa(data);
05632 if (!box) {
05633 ast_log(LOG_ERROR, "Out of memory\n");
05634 LOCAL_USER_REMOVE(u);
05635 return -1;
05636 }
05637
05638 AST_STANDARD_APP_ARGS(args, box);
05639
05640 if (args.options) {
05641 if (strchr(args.options, 'j'))
05642 priority_jump = 1;
05643 }
05644
05645 if ((context = strchr(args.mbox, '@'))) {
05646 *context = '\0';
05647 context++;
05648 }
05649
05650 if (find_user(&svm, context, args.mbox)) {
05651 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
05652 if (priority_jump || option_priority_jumping)
05653 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
05654 ast_log(LOG_WARNING, "VM box %s@%s exists, but extension %s, priority %d doesn't exist\n", box, context, chan->exten, chan->priority + 101);
05655 } else
05656 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
05657 LOCAL_USER_REMOVE(u);
05658 return 0;
05659 }
05660
05661 static int vmauthenticate(struct ast_channel *chan, void *data)
05662 {
05663 struct localuser *u;
05664 char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
05665 struct ast_vm_user vmus;
05666 char *options = NULL;
05667 int silent = 0, skipuser = 0;
05668 int res = -1;
05669
05670 LOCAL_USER_ADD(u);
05671
05672 if (s) {
05673 s = ast_strdupa(s);
05674 if (!s) {
05675 ast_log(LOG_ERROR, "Out of memory\n");
05676 return -1;
05677 }
05678 user = strsep(&s, "|");
05679 options = strsep(&s, "|");
05680 if (user) {
05681 s = user;
05682 user = strsep(&s, "@");
05683 context = strsep(&s, "");
05684 if (!ast_strlen_zero(user))
05685 skipuser++;
05686 ast_copy_string(mailbox, user, sizeof(mailbox));
05687 }
05688 }
05689
05690 if (options) {
05691 silent = (strchr(options, 's')) != NULL;
05692 }
05693
05694 if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
05695 pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
05696 pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
05697 ast_play_and_wait(chan, "auth-thankyou");
05698 res = 0;
05699 }
05700
05701 LOCAL_USER_REMOVE(u);
05702 return res;
05703 }
05704
05705 static char show_voicemail_users_help[] =
05706 "Usage: show voicemail users [for <context>]\n"
05707 " Lists all mailboxes currently set up\n";
05708
05709 static char show_voicemail_zones_help[] =
05710 "Usage: show voicemail zones\n"
05711 " Lists zone message formats\n";
05712
05713 static int handle_show_voicemail_users(int fd, int argc, char *argv[])
05714 {
05715 struct ast_vm_user *vmu = users;
05716 char *output_format = "%-10s %-5s %-25s %-10s %6s\n";
05717
05718 if ((argc < 3) || (argc > 5) || (argc == 4)) return RESULT_SHOWUSAGE;
05719 else if ((argc == 5) && strcmp(argv[3],"for")) return RESULT_SHOWUSAGE;
05720
05721 if (vmu) {
05722 if (argc == 3)
05723 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
05724 else {
05725 int count = 0;
05726 while (vmu) {
05727 if (!strcmp(argv[4],vmu->context))
05728 count++;
05729 vmu = vmu->next;
05730 }
05731 if (count) {
05732 vmu = users;
05733 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
05734 } else {
05735 ast_cli(fd, "No such voicemail context \"%s\"\n", argv[4]);
05736 return RESULT_FAILURE;
05737 }
05738 }
05739 while (vmu) {
05740 char dirname[256];
05741 DIR *vmdir;
05742 struct dirent *vment;
05743 int vmcount = 0;
05744 char count[12];
05745
05746 if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) {
05747 make_dir(dirname, 255, vmu->context, vmu->mailbox, "INBOX");
05748 if ((vmdir = opendir(dirname))) {
05749
05750 while ((vment = readdir(vmdir)))
05751 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
05752 vmcount++;
05753 closedir(vmdir);
05754 }
05755 snprintf(count,sizeof(count),"%d",vmcount);
05756 ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
05757 }
05758 vmu = vmu->next;
05759 }
05760 } else {
05761 ast_cli(fd, "There are no voicemail users currently defined\n");
05762 return RESULT_FAILURE;
05763 }
05764 return RESULT_SUCCESS;
05765 }
05766
05767 static int handle_show_voicemail_zones(int fd, int argc, char *argv[])
05768 {
05769 struct vm_zone *zone = zones;
05770 char *output_format = "%-15s %-20s %-45s\n";
05771
05772 if (argc != 3) return RESULT_SHOWUSAGE;
05773
05774 if (zone) {
05775 ast_cli(fd, output_format, "Zone", "Timezone", "Message Format");
05776 while (zone) {
05777 ast_cli(fd, output_format, zone->name, zone->timezone, zone->msg_format);
05778 zone = zone->next;
05779 }
05780 } else {
05781 ast_cli(fd, "There are no voicemail zones currently defined\n");
05782 return RESULT_FAILURE;
05783 }
05784 return RESULT_SUCCESS;
05785 }
05786
05787 static char *complete_show_voicemail_users(char *line, char *word, int pos, int state)
05788 {
05789 int which = 0;
05790 struct ast_vm_user *vmu = users;
05791 char *context = "";
05792
05793
05794 if (pos > 4)
05795 return NULL;
05796 if (pos == 3) {
05797 if (state == 0)
05798 return strdup("for");
05799 else
05800 return NULL;
05801 }
05802 while (vmu) {
05803 if (!strncasecmp(word, vmu->context, strlen(word))) {
05804 if (context && strcmp(context, vmu->context)) {
05805 if (++which > state) {
05806 return strdup(vmu->context);
05807 }
05808 context = vmu->context;
05809 }
05810 }
05811 vmu = vmu->next;
05812 }
05813 return NULL;
05814 }
05815
05816 static struct ast_cli_entry show_voicemail_users_cli =
05817 { { "show", "voicemail", "users", NULL },
05818 handle_show_voicemail_users, "List defined voicemail boxes",
05819 show_voicemail_users_help, complete_show_voicemail_users };
05820
05821 static struct ast_cli_entry show_voicemail_zones_cli =
05822 { { "show", "voicemail", "zones", NULL },
05823 handle_show_voicemail_zones, "List zone message formats",
05824 show_voicemail_zones_help, NULL };
05825
05826 static int load_config(void)
05827 {
05828 struct ast_vm_user *cur, *l;
05829 struct vm_zone *zcur, *zl;
05830 struct ast_config *cfg;
05831 char *cat;
05832 struct ast_variable *var;
05833 char *notifystr = NULL;
05834 char *astattach;
05835 char *astsearch;
05836 char *astsaycid;
05837 char *send_voicemail;
05838 char *astcallop;
05839 char *astreview;
05840 char *astskipcmd;
05841 char *asthearenv;
05842 char *astsaydurationinfo;
05843 char *astsaydurationminfo;
05844 char *silencestr;
05845 char *maxmsgstr;
05846 char *astdirfwd;
05847 char *thresholdstr;
05848 char *fmt;
05849 char *astemail;
05850 char *astmailcmd = SENDMAIL;
05851 char *s,*q,*stringp;
05852 char *dialoutcxt = NULL;
05853 char *callbackcxt = NULL;
05854 char *exitcxt = NULL;
05855 char *extpc;
05856 char *emaildateformatstr;
05857 int x;
05858 int tmpadsi[4];
05859
05860 cfg = ast_config_load(VOICEMAIL_CONFIG);
05861 ast_mutex_lock(&vmlock);
05862 cur = users;
05863 while (cur) {
05864 l = cur;
05865 cur = cur->next;
05866 ast_set_flag(l, VM_ALLOCED);
05867 free_user(l);
05868 }
05869 zcur = zones;
05870 while (zcur) {
05871 zl = zcur;
05872 zcur = zcur->next;
05873 free_zone(zl);
05874 }
05875 zones = NULL;
05876 zonesl = NULL;
05877 users = NULL;
05878 usersl = NULL;
05879 memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
05880
05881 if (cfg) {
05882
05883
05884
05885 if (!(astattach = ast_variable_retrieve(cfg, "general", "attach")))
05886 astattach = "yes";
05887 ast_set2_flag((&globalflags), ast_true(astattach), VM_ATTACH);
05888
05889 if (!(astsearch = ast_variable_retrieve(cfg, "general", "searchcontexts")))
05890 astsearch = "no";
05891 ast_set2_flag((&globalflags), ast_true(astsearch), VM_SEARCH);
05892
05893 #ifdef USE_ODBC_STORAGE
05894 strcpy(odbc_database, "asterisk");
05895 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
05896 ast_copy_string(odbc_database, thresholdstr, sizeof(odbc_database));
05897 }
05898 strcpy(odbc_table, "voicemessages");
05899 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbctable"))) {
05900 ast_copy_string(odbc_table, thresholdstr, sizeof(odbc_table));
05901 }
05902 #endif
05903
05904 strcpy(mailcmd, SENDMAIL);
05905 if ((astmailcmd = ast_variable_retrieve(cfg, "general", "mailcmd")))
05906 ast_copy_string(mailcmd, astmailcmd, sizeof(mailcmd));
05907
05908 maxsilence = 0;
05909 if ((silencestr = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
05910 maxsilence = atoi(silencestr);
05911 if (maxsilence > 0)
05912 maxsilence *= 1000;
05913 }
05914
05915 if (!(maxmsgstr = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
05916 maxmsg = MAXMSG;
05917 } else {
05918 maxmsg = atoi(maxmsgstr);
05919 if (maxmsg <= 0) {
05920 ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", maxmsgstr, MAXMSG);
05921 maxmsg = MAXMSG;
05922 } else if (maxmsg > MAXMSGLIMIT) {
05923 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, maxmsgstr);
05924 maxmsg = MAXMSGLIMIT;
05925 }
05926 }
05927
05928
05929 if ((emaildateformatstr = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
05930 ast_copy_string(emaildateformat, emaildateformatstr, sizeof(emaildateformat));
05931 }
05932
05933
05934 if ((extpc = ast_variable_retrieve(cfg, "general", "externpass"))) {
05935 ast_copy_string(ext_pass_cmd,extpc,sizeof(ext_pass_cmd));
05936 }
05937
05938
05939
05940 if ((notifystr = ast_variable_retrieve(cfg, "general", "externnotify"))) {
05941 ast_copy_string(externnotify, notifystr, sizeof(externnotify));
05942 ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify);
05943 } else {
05944 externnotify[0] = '\0';
05945 }
05946
05947
05948 silencethreshold = 256;
05949 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
05950 silencethreshold = atoi(thresholdstr);
05951
05952 if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
05953 astemail = ASTERISK_USERNAME;
05954 ast_copy_string(serveremail, astemail, sizeof(serveremail));
05955
05956 vmmaxmessage = 0;
05957 if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
05958 if (sscanf(s, "%d", &x) == 1) {
05959 vmmaxmessage = x;
05960 } else {
05961 ast_log(LOG_WARNING, "Invalid max message time length\n");
05962 }
05963 }
05964
05965 vmminmessage = 0;
05966 if ((s = ast_variable_retrieve(cfg, "general", "minmessage"))) {
05967 if (sscanf(s, "%d", &x) == 1) {
05968 vmminmessage = x;
05969 if (maxsilence <= vmminmessage)
05970 ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
05971 } else {
05972 ast_log(LOG_WARNING, "Invalid min message time length\n");
05973 }
05974 }
05975 fmt = ast_variable_retrieve(cfg, "general", "format");
05976 if (!fmt)
05977 fmt = "wav";
05978 ast_copy_string(vmfmts, fmt, sizeof(vmfmts));
05979
05980 skipms = 3000;
05981 if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
05982 if (sscanf(s, "%d", &x) == 1) {
05983 maxgreet = x;
05984 } else {
05985 ast_log(LOG_WARNING, "Invalid max message greeting length\n");
05986 }
05987 }
05988
05989 if ((s = ast_variable_retrieve(cfg, "general", "skipms"))) {
05990 if (sscanf(s, "%d", &x) == 1) {
05991 skipms = x;
05992 } else {
05993 ast_log(LOG_WARNING, "Invalid skipms value\n");
05994 }
05995 }
05996
05997 maxlogins = 3;
05998 if ((s = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
05999 if (sscanf(s, "%d", &x) == 1) {
06000 maxlogins = x;
06001 } else {
06002 ast_log(LOG_WARNING, "Invalid max failed login attempts\n");
06003 }
06004 }
06005
06006
06007 if (!(astattach = ast_variable_retrieve(cfg, "general", "forcename")))
06008 astattach = "no";
06009 ast_set2_flag((&globalflags), ast_true(astattach), VM_FORCENAME);
06010
06011
06012 if (!(astattach = ast_variable_retrieve(cfg, "general", "forcegreetings")))
06013 astattach = "no";
06014 ast_set2_flag((&globalflags), ast_true(astattach), VM_FORCEGREET);
06015
06016 if ((s = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))){
06017 ast_log(LOG_DEBUG,"VM_CID Internal context string: %s\n",s);
06018 stringp = ast_strdupa(s);
06019 for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
06020 if (!ast_strlen_zero(stringp)) {
06021 q = strsep(&stringp,",");
06022 while ((*q == ' ')||(*q == '\t'))
06023 q++;
06024 ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
06025 ast_log(LOG_DEBUG,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
06026 } else {
06027 cidinternalcontexts[x][0] = '\0';
06028 }
06029 }
06030 }
06031 if (!(astreview = ast_variable_retrieve(cfg, "general", "review"))){
06032 ast_log(LOG_DEBUG,"VM Review Option disabled globally\n");
06033 astreview = "no";
06034 }
06035 ast_set2_flag((&globalflags), ast_true(astreview), VM_REVIEW);
06036
06037 if (!(astcallop = ast_variable_retrieve(cfg, "general", "operator"))){
06038 ast_log(LOG_DEBUG,"VM Operator break disabled globally\n");
06039 astcallop = "no";
06040 }
06041 ast_set2_flag((&globalflags), ast_true(astcallop), VM_OPERATOR);
06042
06043 if (!(astsaycid = ast_variable_retrieve(cfg, "general", "saycid"))) {
06044 ast_log(LOG_DEBUG,"VM CID Info before msg disabled globally\n");
06045 astsaycid = "no";
06046 }
06047 ast_set2_flag((&globalflags), ast_true(astsaycid), VM_SAYCID);
06048
06049 if (!(send_voicemail = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
06050 ast_log(LOG_DEBUG,"Send Voicemail msg disabled globally\n");
06051 send_voicemail = "no";
06052 }
06053 ast_set2_flag((&globalflags), ast_true(send_voicemail), VM_SVMAIL);
06054
06055 if (!(asthearenv = ast_variable_retrieve(cfg, "general", "envelope"))) {
06056 ast_log(LOG_DEBUG,"ENVELOPE before msg enabled globally\n");
06057 asthearenv = "yes";
06058 }
06059 ast_set2_flag((&globalflags), ast_true(asthearenv), VM_ENVELOPE);
06060
06061 if (!(astsaydurationinfo = ast_variable_retrieve(cfg, "general", "sayduration"))) {
06062 ast_log(LOG_DEBUG,"Duration info before msg enabled globally\n");
06063 astsaydurationinfo = "yes";
06064 }
06065 ast_set2_flag((&globalflags), ast_true(astsaydurationinfo), VM_SAYDURATION);
06066
06067 saydurationminfo = 2;
06068 if ((astsaydurationminfo = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
06069 if (sscanf(astsaydurationminfo, "%d", &x) == 1) {
06070 saydurationminfo = x;
06071 } else {
06072 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
06073 }
06074 }
06075
06076 if (!(astskipcmd = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
06077 ast_log(LOG_DEBUG,"We are not going to skip to the next msg after save/delete\n");
06078 astskipcmd = "no";
06079 }
06080 ast_set2_flag((&globalflags), ast_true(astskipcmd), VM_SKIPAFTERCMD);
06081
06082 if ((dialoutcxt = ast_variable_retrieve(cfg, "general", "dialout"))) {
06083 ast_copy_string(dialcontext, dialoutcxt, sizeof(dialcontext));
06084 ast_log(LOG_DEBUG, "found dialout context: %s\n", dialcontext);
06085 } else {
06086 dialcontext[0] = '\0';
06087 }
06088
06089 if ((callbackcxt = ast_variable_retrieve(cfg, "general", "callback"))) {
06090 ast_copy_string(callcontext, callbackcxt, sizeof(callcontext));
06091 ast_log(LOG_DEBUG, "found callback context: %s\n", callcontext);
06092 } else {
06093 callcontext[0] = '\0';
06094 }
06095
06096 if ((exitcxt = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
06097 ast_copy_string(exitcontext, exitcxt, sizeof(exitcontext));
06098 ast_log(LOG_DEBUG, "found operator context: %s\n", exitcontext);
06099 } else {
06100 exitcontext[0] = '\0';
06101 }
06102
06103 if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory")))
06104 astdirfwd = "no";
06105 ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD);
06106 cat = ast_category_browse(cfg, NULL);
06107 while (cat) {
06108 if (strcasecmp(cat, "general")) {
06109 var = ast_variable_browse(cfg, cat);
06110 if (strcasecmp(cat, "zonemessages")) {
06111
06112 while (var) {
06113 append_mailbox(cat, var->name, var->value);
06114 var = var->next;
06115 }
06116 } else {
06117
06118 while (var) {
06119 struct vm_zone *z;
06120 z = malloc(sizeof(struct vm_zone));
06121 if (z != NULL) {
06122 char *msg_format, *timezone;
06123 msg_format = ast_strdupa(var->value);
06124 if (msg_format != NULL) {
06125 timezone = strsep(&msg_format, "|");
06126 if (msg_format) {
06127 ast_copy_string(z->name, var->name, sizeof(z->name));
06128 ast_copy_string(z->timezone, timezone, sizeof(z->timezone));
06129 ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
06130 z->next = NULL;
06131 if (zones) {
06132 zonesl->next = z;
06133 zonesl = z;
06134 } else {
06135 zones = z;
06136 zonesl = z;
06137 }
06138 } else {
06139 ast_log(LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
06140 free(z);
06141 }
06142 } else {
06143 ast_log(LOG_WARNING, "Out of memory while reading voicemail config\n");
06144 free(z);
06145 return -1;
06146 }
06147 } else {
06148 ast_log(LOG_WARNING, "Out of memory while reading voicemail config\n");
06149 return -1;
06150 }
06151 var = var->next;
06152 }
06153 }
06154 }
06155 cat = ast_category_browse(cfg, cat);
06156 }
06157 memset(fromstring,0,sizeof(fromstring));
06158 memset(pagerfromstring,0,sizeof(pagerfromstring));
06159 memset(emailtitle,0,sizeof(emailtitle));
06160 strcpy(charset, "ISO-8859-1");
06161 if (emailbody) {
06162 free(emailbody);
06163 emailbody = NULL;
06164 }
06165 if (emailsubject) {
06166 free(emailsubject);
06167 emailsubject = NULL;
06168 }
06169 if (pagerbody) {
06170 free(pagerbody);
06171 pagerbody = NULL;
06172 }
06173 if (pagersubject) {
06174 free(pagersubject);
06175 pagersubject = NULL;
06176 }
06177 if ((s=ast_variable_retrieve(cfg, "general", "pbxskip")))
06178 ast_set2_flag((&globalflags), ast_true(s), VM_PBXSKIP);
06179 if ((s=ast_variable_retrieve(cfg, "general", "fromstring")))
06180 ast_copy_string(fromstring,s,sizeof(fromstring));
06181 if ((s=ast_variable_retrieve(cfg, "general", "pagerfromstring")))
06182 ast_copy_string(pagerfromstring,s,sizeof(pagerfromstring));
06183 if ((s=ast_variable_retrieve(cfg, "general", "charset")))
06184 ast_copy_string(charset,s,sizeof(charset));
06185 if ((s=ast_variable_retrieve(cfg, "general", "adsifdn"))) {
06186 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
06187 for (x=0; x<4; x++) {
06188 memcpy(&adsifdn[x], &tmpadsi[x], 1);
06189 }
06190 }
06191 if ((s=ast_variable_retrieve(cfg, "general", "adsisec"))) {
06192 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
06193 for (x=0; x<4; x++) {
06194 memcpy(&adsisec[x], &tmpadsi[x], 1);
06195 }
06196 }
06197 if ((s=ast_variable_retrieve(cfg, "general", "adsiver")))
06198 if (atoi(s)) {
06199 adsiver = atoi(s);
06200 }
06201 if ((s=ast_variable_retrieve(cfg, "general", "emailtitle"))) {
06202 ast_log(LOG_NOTICE, "Keyword 'emailtitle' is DEPRECATED, please use 'emailsubject' instead.\n");
06203 ast_copy_string(emailtitle,s,sizeof(emailtitle));
06204 }
06205 if ((s=ast_variable_retrieve(cfg, "general", "emailsubject")))
06206 emailsubject = strdup(s);
06207 if ((s=ast_variable_retrieve(cfg, "general", "emailbody"))) {
06208 char *tmpread, *tmpwrite;
06209 emailbody = strdup(s);
06210
06211
06212 tmpread = tmpwrite = emailbody;
06213 while ((tmpwrite = strchr(tmpread,'\\'))) {
06214 int len = strlen("\n");
06215 switch (tmpwrite[1]) {
06216 case 'n':
06217 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06218 strncpy(tmpwrite,"\n",len);
06219 break;
06220 case 't':
06221 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06222 strncpy(tmpwrite,"\t",len);
06223 break;
06224 default:
06225 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n",tmpwrite[1]);
06226 }
06227 tmpread = tmpwrite+len;
06228 }
06229 }
06230 if ((s=ast_variable_retrieve(cfg, "general", "pagersubject")))
06231 pagersubject = strdup(s);
06232 if ((s=ast_variable_retrieve(cfg, "general", "pagerbody"))) {
06233 char *tmpread, *tmpwrite;
06234 pagerbody = strdup(s);
06235
06236
06237 tmpread = tmpwrite = pagerbody;
06238 while ((tmpwrite = strchr(tmpread,'\\'))) {
06239 int len = strlen("\n");
06240 switch (tmpwrite[1]) {
06241 case 'n':
06242 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06243 strncpy(tmpwrite,"\n",len);
06244 break;
06245 case 't':
06246 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06247 strncpy(tmpwrite,"\t",len);
06248 break;
06249 default:
06250 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n",tmpwrite[1]);
06251 }
06252 tmpread = tmpwrite+len;
06253 }
06254 }
06255 ast_mutex_unlock(&vmlock);
06256 ast_config_destroy(cfg);
06257 return 0;
06258 } else {
06259 ast_mutex_unlock(&vmlock);
06260 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
06261 return 0;
06262 }
06263 }
06264
06265 int reload(void)
06266 {
06267 return(load_config());
06268 }
06269
06270 int unload_module(void)
06271 {
06272 int res;
06273
06274 res = ast_unregister_application(app);
06275 res |= ast_unregister_application(app2);
06276 res |= ast_unregister_application(app3);
06277 res |= ast_unregister_application(app4);
06278 res |= ast_cli_unregister(&show_voicemail_users_cli);
06279 res |= ast_cli_unregister(&show_voicemail_zones_cli);
06280 ast_uninstall_vm_functions();
06281
06282 STANDARD_HANGUP_LOCALUSERS;
06283
06284 return res;
06285 }
06286
06287 int load_module(void)
06288 {
06289 int res;
06290 res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
06291 res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
06292 res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
06293 res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
06294 if (res)
06295 return(res);
06296
06297 if ((res=load_config())) {
06298 return(res);
06299 }
06300
06301 ast_cli_register(&show_voicemail_users_cli);
06302 ast_cli_register(&show_voicemail_zones_cli);
06303
06304
06305 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
06306
06307 ast_install_vm_functions(has_voicemail, messagecount);
06308
06309 #if defined(USE_ODBC_STORAGE) && !defined(EXTENDED_ODBC_STORAGE)
06310 ast_log(LOG_WARNING, "The current ODBC storage table format will be changed soon."
06311 "Please update your tables as per the README and edit the apps/Makefile "
06312 "and uncomment the line containing EXTENDED_ODBC_STORAGE to enable the "
06313 "new table format.\n");
06314 #endif
06315
06316 return res;
06317 }
06318
06319 char *description(void)
06320 {
06321 return tdesc;
06322 }
06323
06324 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
06325 {
06326 int cmd = 0;
06327 char destination[80] = "";
06328 int retries = 0;
06329
06330 if (!num) {
06331 ast_verbose( VERBOSE_PREFIX_3 "Destination number will be entered manually\n");
06332 while (retries < 3 && cmd != 't') {
06333 destination[1] = '\0';
06334 destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
06335 if (!cmd)
06336 destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
06337 if (!cmd)
06338 destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
06339 if (!cmd) {
06340 cmd = ast_waitfordigit(chan, 6000);
06341 if (cmd)
06342 destination[0] = cmd;
06343 }
06344 if (!cmd) {
06345 retries++;
06346 } else {
06347
06348 if (cmd < 0)
06349 return 0;
06350 if (cmd == '*') {
06351 ast_verbose( VERBOSE_PREFIX_3 "User hit '*' to cancel outgoing call\n");
06352 return 0;
06353 }
06354 if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0)
06355 retries++;
06356 else
06357 cmd = 't';
06358 }
06359 }
06360 if (retries >= 3) {
06361 return 0;
06362 }
06363
06364 } else {
06365 ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
06366 ast_copy_string(destination, num, sizeof(destination));
06367 }
06368
06369 if (!ast_strlen_zero(destination)) {
06370 if (destination[strlen(destination) -1 ] == '*')
06371 return 0;
06372 ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
06373 ast_copy_string(chan->exten, destination, sizeof(chan->exten));
06374 ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
06375 chan->priority = 0;
06376 return 9;
06377 }
06378 return 0;
06379 }
06380
06381 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg,
06382 int option, signed char record_gain)
06383 {
06384 int res = 0;
06385 char filename[256],*origtime, *cid, *context, *name, *num;
06386 struct ast_config *msg_cfg;
06387 int retries = 0;
06388
06389 vms->starting = 0;
06390 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
06391
06392
06393
06394 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
06395 snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
06396 RETRIEVE(vms->curdir, vms->curmsg);
06397 msg_cfg = ast_config_load(filename);
06398 DISPOSE(vms->curdir, vms->curmsg);
06399 if (!msg_cfg) {
06400 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06401 return 0;
06402 }
06403
06404 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")))
06405 return 0;
06406
06407 cid = ast_variable_retrieve(msg_cfg, "message", "callerid");
06408
06409 context = ast_variable_retrieve(msg_cfg, "message", "context");
06410 if (!strncasecmp("macro",context,5))
06411 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
06412
06413 if (option == 3) {
06414
06415 if (!res)
06416 res = play_message_datetime(chan, vmu, origtime, filename);
06417 if (!res)
06418 res = play_message_callerid(chan, vms, cid, context, 0);
06419 } else if (option == 2) {
06420
06421 if (!ast_strlen_zero(cid)) {
06422 ast_callerid_parse(cid, &name, &num);
06423 while ((res > -1) && (res != 't')) {
06424 switch(res) {
06425 case '1':
06426 if (num) {
06427
06428 res = dialout(chan, vmu, num, vmu->callback);
06429 if (res)
06430 return 9;
06431 } else {
06432 res = '2';
06433 }
06434 break;
06435
06436 case '2':
06437
06438 if (!ast_strlen_zero(vmu->dialout)) {
06439 res = dialout(chan, vmu, NULL, vmu->dialout);
06440 if (res)
06441 return 9;
06442 } else {
06443 ast_verbose( VERBOSE_PREFIX_3 "Caller can not specify callback number - no dialout context available\n");
06444 res = ast_play_and_wait(chan, "vm-sorry");
06445 }
06446 return res;
06447 case '*':
06448 res = 't';
06449 break;
06450 case '3':
06451 case '4':
06452 case '5':
06453 case '6':
06454 case '7':
06455 case '8':
06456 case '9':
06457 case '0':
06458
06459 res = ast_play_and_wait(chan, "vm-sorry");
06460 retries++;
06461 break;
06462 default:
06463 if (num) {
06464 ast_verbose( VERBOSE_PREFIX_3 "Confirm CID number '%s' is number to use for callback\n", num);
06465 res = ast_play_and_wait(chan, "vm-num-i-have");
06466 if (!res)
06467 res = play_message_callerid(chan, vms, num, vmu->context, 1);
06468 if (!res)
06469 res = ast_play_and_wait(chan, "vm-tocallnum");
06470
06471 if (!ast_strlen_zero(vmu->dialout)) {
06472 if (!res)
06473 res = ast_play_and_wait(chan, "vm-calldiffnum");
06474 }
06475 } else {
06476 res = ast_play_and_wait(chan, "vm-nonumber");
06477 if (!ast_strlen_zero(vmu->dialout)) {
06478 if (!res)
06479 res = ast_play_and_wait(chan, "vm-toenternumber");
06480 }
06481 }
06482 if (!res)
06483 res = ast_play_and_wait(chan, "vm-star-cancel");
06484 if (!res)
06485 res = ast_waitfordigit(chan, 6000);
06486 if (!res)
06487 retries++;
06488 if (retries > 3)
06489 res = 't';
06490 break;
06491
06492 }
06493 if (res == 't')
06494 res = 0;
06495 else if (res == '*')
06496 res = -1;
06497 }
06498 }
06499
06500 }
06501 else if (option == 1) {
06502
06503 if (!ast_strlen_zero(cid)) {
06504 ast_callerid_parse(cid, &name, &num);
06505 if (!num) {
06506 ast_verbose(VERBOSE_PREFIX_3 "No CID number available, no reply sent\n");
06507 if (!res)
06508 res = ast_play_and_wait(chan, "vm-nonumber");
06509 return res;
06510 } else {
06511 if (find_user(NULL, vmu->context, num)) {
06512 struct leave_vm_options leave_options;
06513
06514 ast_verbose(VERBOSE_PREFIX_3 "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
06515
06516 memset(&leave_options, 0, sizeof(leave_options));
06517 leave_options.record_gain = record_gain;
06518 res = leave_voicemail(chan, num, &leave_options);
06519 if (!res)
06520 res = 't';
06521 return res;
06522 } else {
06523
06524 ast_verbose( VERBOSE_PREFIX_3 "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
06525 ast_play_and_wait(chan, "vm-nobox");
06526 res = 't';
06527 return res;
06528 }
06529 }
06530 res = 0;
06531 }
06532 }
06533
06534 ast_config_destroy(msg_cfg);
06535
06536 if (!res) {
06537 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
06538 vms->heard[msg] = 1;
06539 res = wait_file(chan, vms, vms->fn);
06540 }
06541 return res;
06542 }
06543
06544 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
06545 int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
06546 signed char record_gain)
06547 {
06548
06549 int res = 0;
06550 int cmd = 0;
06551 int max_attempts = 3;
06552 int attempts = 0;
06553 int recorded = 0;
06554 int message_exists = 0;
06555 signed char zero_gain = 0;
06556
06557
06558
06559 if (duration == NULL) {
06560 ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
06561 return -1;
06562 }
06563
06564 cmd = '3';
06565
06566 while ((cmd >= 0) && (cmd != 't')) {
06567 switch (cmd) {
06568 case '1':
06569 if (!message_exists) {
06570
06571 cmd = '3';
06572 break;
06573 } else {
06574
06575 ast_verbose(VERBOSE_PREFIX_3 "Saving message as is\n");
06576 ast_streamfile(chan, "vm-msgsaved", chan->language);
06577 ast_waitstream(chan, "");
06578 STORE(recordfile, vmu->mailbox, vmu->context, -1);
06579 DISPOSE(recordfile, -1);
06580 cmd = 't';
06581 return res;
06582 }
06583 case '2':
06584
06585 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the message\n");
06586 ast_streamfile(chan, recordfile, chan->language);
06587 cmd = ast_waitstream(chan, AST_DIGIT_ANY);
06588 break;
06589 case '3':
06590 message_exists = 0;
06591
06592 if (recorded == 1)
06593 ast_verbose(VERBOSE_PREFIX_3 "Re-recording the message\n");
06594 else
06595 ast_verbose(VERBOSE_PREFIX_3 "Recording the message\n");
06596 if (recorded && outsidecaller) {
06597 cmd = ast_play_and_wait(chan, INTRO);
06598 cmd = ast_play_and_wait(chan, "beep");
06599 }
06600 recorded = 1;
06601
06602 if (record_gain)
06603 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06604 cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir);
06605 if (record_gain)
06606 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06607 if (cmd == -1) {
06608
06609 return cmd;
06610 }
06611 if (cmd == '0') {
06612 break;
06613 } else if (cmd == '*') {
06614 break;
06615 }
06616 #if 0
06617 else if (vmu->review && (*duration < 5)) {
06618
06619 ast_verbose(VERBOSE_PREFIX_3 "Message too short\n");
06620 cmd = ast_play_and_wait(chan, "vm-tooshort");
06621 cmd = vm_delete(recordfile);
06622 break;
06623 }
06624 else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
06625
06626 ast_verbose(VERBOSE_PREFIX_3 "Nothing recorded\n");
06627 cmd = vm_delete(recordfile);
06628 cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
06629 if (!cmd)
06630 cmd = ast_play_and_wait(chan, "vm-speakup");
06631 break;
06632 }
06633 #endif
06634 else {
06635
06636 message_exists = 1;
06637 cmd = 0;
06638 }
06639 break;
06640 case '4':
06641 case '5':
06642 case '6':
06643 case '7':
06644 case '8':
06645 case '9':
06646 case '*':
06647 case '#':
06648 cmd = ast_play_and_wait(chan, "vm-sorry");
06649 break;
06650 #if 0
06651
06652
06653 case '*':
06654
06655 cmd = ast_play_and_wait(chan, "vm-deleted");
06656 cmd = vm_delete(recordfile);
06657 if (outsidecaller) {
06658 res = vm_exec(chan, NULL);
06659 return res;
06660 }
06661 else
06662 return 1;
06663 #endif
06664 case '0':
06665 if (message_exists || recorded) {
06666 cmd = ast_play_and_wait(chan, "vm-saveoper");
06667 if (!cmd)
06668 cmd = ast_waitfordigit(chan, 3000);
06669 if (cmd == '1') {
06670 ast_play_and_wait(chan, "vm-msgsaved");
06671 cmd = '0';
06672 } else {
06673 ast_play_and_wait(chan, "vm-deleted");
06674 DELETE(recordfile, -1, recordfile);
06675 cmd = '0';
06676 }
06677 }
06678 return cmd;
06679 default:
06680
06681
06682
06683 if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
06684 return cmd;
06685 if (message_exists) {
06686 cmd = ast_play_and_wait(chan, "vm-review");
06687 }
06688 else {
06689 cmd = ast_play_and_wait(chan, "vm-torerecord");
06690 if (!cmd)
06691 cmd = ast_waitfordigit(chan, 600);
06692 }
06693
06694 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
06695 cmd = ast_play_and_wait(chan, "vm-reachoper");
06696 if (!cmd)
06697 cmd = ast_waitfordigit(chan, 600);
06698 }
06699 #if 0
06700 if (!cmd)
06701 cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
06702 #endif
06703 if (!cmd)
06704 cmd = ast_waitfordigit(chan, 6000);
06705 if (!cmd) {
06706 attempts++;
06707 }
06708 if (attempts > max_attempts) {
06709 cmd = 't';
06710 }
06711 }
06712 }
06713 if (outsidecaller)
06714 ast_play_and_wait(chan, "vm-goodbye");
06715 if (cmd == 't')
06716 cmd = 0;
06717 return cmd;
06718 }
06719
06720
06721 int usecount(void)
06722 {
06723 int res;
06724 STANDARD_USECOUNT(res);
06725 return res;
06726 }
06727
06728 char *key()
06729 {
06730 return ASTERISK_GPL_KEY;
06731 }
06732