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