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