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