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