00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 #include <errno.h>
00042 #include <unistd.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #include <sys/time.h>
00047 #include <sys/stat.h>
00048 #include <sys/types.h>
00049 #include <sys/mman.h>
00050 #include <time.h>
00051 #include <dirent.h>
00052
00053 #include "asterisk.h"
00054
00055 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 41065 $")
00056
00057 #include "asterisk/lock.h"
00058 #include "asterisk/file.h"
00059 #include "asterisk/logger.h"
00060 #include "asterisk/channel.h"
00061 #include "asterisk/pbx.h"
00062 #include "asterisk/options.h"
00063 #include "asterisk/config.h"
00064 #include "asterisk/say.h"
00065 #include "asterisk/module.h"
00066 #include "asterisk/adsi.h"
00067 #include "asterisk/app.h"
00068 #include "asterisk/manager.h"
00069 #include "asterisk/dsp.h"
00070 #include "asterisk/localtime.h"
00071 #include "asterisk/cli.h"
00072 #include "asterisk/utils.h"
00073 #ifdef USE_ODBC_STORAGE
00074 #include "asterisk/res_odbc.h"
00075 #endif
00076
00077 #define COMMAND_TIMEOUT 5000
00078 #define VOICEMAIL_DIR_MODE 0700
00079 #define VOICEMAIL_FILE_MODE 0600
00080
00081 #define VOICEMAIL_CONFIG "voicemail.conf"
00082 #define ASTERISK_USERNAME "asterisk"
00083
00084
00085
00086 #define SENDMAIL "/usr/sbin/sendmail -t"
00087
00088 #define INTRO "vm-intro"
00089
00090 #define MAXMSG 100
00091 #define MAXMSGLIMIT 9999
00092
00093 #define BASEMAXINLINE 256
00094 #define BASELINELEN 72
00095 #define BASEMAXINLINE 256
00096 #define eol "\r\n"
00097
00098 #define MAX_DATETIME_FORMAT 512
00099 #define MAX_NUM_CID_CONTEXTS 10
00100
00101 #define VM_REVIEW (1 << 0)
00102 #define VM_OPERATOR (1 << 1)
00103 #define VM_SAYCID (1 << 2)
00104 #define VM_SVMAIL (1 << 3)
00105 #define VM_ENVELOPE (1 << 4)
00106 #define VM_SAYDURATION (1 << 5)
00107 #define VM_SKIPAFTERCMD (1 << 6)
00108 #define VM_FORCENAME (1 << 7)
00109 #define VM_FORCEGREET (1 << 8)
00110 #define VM_PBXSKIP (1 << 9)
00111 #define VM_DIRECFORWARD (1 << 10)
00112 #define VM_ATTACH (1 << 11)
00113 #define VM_DELETE (1 << 12)
00114 #define VM_ALLOCED (1 << 13)
00115 #define VM_SEARCH (1 << 14)
00116
00117 #define ERROR_LOCK_PATH -100
00118
00119 enum {
00120 OPT_SILENT = (1 << 0),
00121 OPT_BUSY_GREETING = (1 << 1),
00122 OPT_UNAVAIL_GREETING = (1 << 2),
00123 OPT_RECORDGAIN = (1 << 3),
00124 OPT_PREPEND_MAILBOX = (1 << 4),
00125 OPT_PRIORITY_JUMP = (1 << 5),
00126 } vm_option_flags;
00127
00128 enum {
00129 OPT_ARG_RECORDGAIN = 0,
00130 OPT_ARG_ARRAY_SIZE = 1,
00131 } vm_option_args;
00132
00133 AST_APP_OPTIONS(vm_app_options, {
00134 AST_APP_OPTION('s', OPT_SILENT),
00135 AST_APP_OPTION('b', OPT_BUSY_GREETING),
00136 AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
00137 AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
00138 AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
00139 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00140 });
00141
00142 static int load_config(void);
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
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 char vmcontext[256];
03452 memcpy(old_context, chan->context, sizeof(chan->context));
03453 memcpy(old_exten, chan->exten, sizeof(chan->exten));
03454 old_priority = chan->priority;
03455
03456
03457 sprintf(vmcontext, "%s||v", context ? context : "default");
03458 res = pbx_exec(chan, app, vmcontext, 1);
03459
03460 ast_copy_string(username, chan->exten, sizeof(username));
03461
03462
03463 memcpy(chan->context, old_context, sizeof(chan->context));
03464 memcpy(chan->exten, old_exten, sizeof(chan->exten));
03465 chan->priority = old_priority;
03466
03467 } else {
03468 ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
03469 ast_clear_flag((&globalflags), VM_DIRECFORWARD);
03470 }
03471 } else {
03472
03473 res = ast_streamfile(chan, "vm-extension", chan->language);
03474 if (res)
03475 break;
03476 if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
03477 break;
03478 }
03479
03480
03481 if (ast_strlen_zero(username))
03482 continue;
03483 stringp = username;
03484 s = strsep(&stringp, "*");
03485
03486 valid_extensions = 1;
03487 while (s) {
03488
03489 if (strcmp(s,sender->mailbox) && (receiver = find_user(NULL, context, s))) {
03490 if (!extensions)
03491 vmtmp = extensions = receiver;
03492 else {
03493 vmtmp->next = receiver;
03494 vmtmp = receiver;
03495 }
03496 found++;
03497 } else {
03498 valid_extensions = 0;
03499 break;
03500 }
03501 s = strsep(&stringp, "*");
03502 }
03503
03504 if (valid_extensions)
03505 break;
03506
03507 res = ast_play_and_wait(chan, "pbx-invalid");
03508 }
03509
03510 if (!extensions || !valid_extensions)
03511 return res;
03512 vmtmp = extensions;
03513 if (flag==1) {
03514 struct leave_vm_options leave_options;
03515 char mailbox[AST_MAX_EXTENSION * 2 + 2];
03516 snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
03517
03518
03519 memset(&leave_options, 0, sizeof(leave_options));
03520 leave_options.record_gain = record_gain;
03521 cmd = leave_voicemail(chan, mailbox, &leave_options);
03522 } else {
03523
03524 RETRIEVE(dir, curmsg);
03525 cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, context, record_gain);
03526 if (!cmd) {
03527 while (!res && vmtmp) {
03528
03529
03530
03531 snprintf(todir, sizeof(todir), "%s%s/%s/INBOX", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
03532 snprintf(sys, sizeof(sys), "mkdir -p %s\n", todir);
03533 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmtmp->mailbox, vmtmp->context);
03534 ast_log(LOG_DEBUG, "%s", sys);
03535 ast_safe_system(sys);
03536
03537 res = count_messages(receiver, todir);
03538
03539 if ( (res == ERROR_LOCK_PATH) || (res < 0) ) {
03540 if (res == ERROR_LOCK_PATH)
03541 ast_log(LOG_WARNING, "Unable to lock the directory %s to forward the requested vmail msg!\n", todir);
03542 else
03543 ast_log(LOG_WARNING, "Unable to determine how many msgs are in the destination folder!\n");
03544 break;
03545 }
03546 todircount = res;
03547 ast_copy_string(tmp, fmt, sizeof(tmp));
03548 stringp = tmp;
03549 while ((s = strsep(&stringp, "|"))) {
03550
03551 if (!strcasecmp(s, "wav49"))
03552 s = "WAV";
03553 snprintf(sys, sizeof(sys), "cp %s/msg%04d.%s %s/msg%04d.%s\n", dir, curmsg, s, todir, todircount, s);
03554 ast_log(LOG_DEBUG, "%s", sys);
03555 ast_safe_system(sys);
03556 }
03557 snprintf(sys, sizeof(sys), "cp %s/msg%04d.txt %s/msg%04d.txt\n", dir, curmsg, todir, todircount);
03558 ast_log(LOG_DEBUG, "%s", sys);
03559 ast_safe_system(sys);
03560 snprintf(fn, sizeof(fn), "%s/msg%04d", todir,todircount);
03561
03562 STORE(todir, vmtmp->mailbox, vmtmp->context, todircount);
03563
03564
03565 snprintf(miffile, sizeof(miffile), "%s/msg%04d.txt", dir, curmsg);
03566 if ((mif=ast_config_load(miffile))) {
03567
03568
03569 snprintf(callerid, sizeof(callerid), "FWD from: %s from %s", sender->fullname, ast_variable_retrieve(mif, NULL, "callerid"));
03570 s = ast_variable_retrieve(mif, NULL, "duration");
03571 if (s)
03572 duration = atoi(s);
03573 else
03574 duration = 0;
03575 if (!ast_strlen_zero(vmtmp->email)) {
03576 int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
03577 char *myserveremail = serveremail;
03578 attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
03579 if (!ast_strlen_zero(vmtmp->serveremail))
03580 myserveremail = vmtmp->serveremail;
03581 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, chan->cid.cid_num, chan->cid.cid_name, fn, tmp, duration, attach_user_voicemail);
03582 }
03583
03584 if (!ast_strlen_zero(vmtmp->pager)) {
03585 char *myserveremail = serveremail;
03586 if (!ast_strlen_zero(vmtmp->serveremail))
03587 myserveremail = vmtmp->serveremail;
03588 sendpage(myserveremail, vmtmp->pager, todircount, vmtmp->context, vmtmp->mailbox, chan->cid.cid_num, chan->cid.cid_name, duration, vmtmp);
03589 }
03590
03591 ast_config_destroy(mif);
03592 }
03593
03594 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
03595 run_externnotify(vmtmp->context, vmtmp->mailbox);
03596
03597 saved_messages++;
03598 vmfree = vmtmp;
03599 vmtmp = vmtmp->next;
03600 free_user(vmfree);
03601 }
03602 if (saved_messages > 0) {
03603
03604
03605
03606
03607
03608
03609
03610
03611 res = ast_play_and_wait(chan, "vm-msgsaved");
03612 }
03613 }
03614 }
03615 return res ? res : cmd;
03616 }
03617
03618 static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
03619 {
03620 int res;
03621 if ((res = ast_streamfile(chan, file, chan->language)))
03622 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
03623 if (!res)
03624 res = ast_waitstream(chan, AST_DIGIT_ANY);
03625 return res;
03626 }
03627
03628 static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
03629 {
03630 return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms);
03631 }
03632
03633 static int play_message_category(struct ast_channel *chan, char *category)
03634 {
03635 int res = 0;
03636
03637 if (!ast_strlen_zero(category))
03638 res = ast_play_and_wait(chan, category);
03639
03640 if (res) {
03641 ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
03642 res = 0;
03643 }
03644
03645 return res;
03646 }
03647
03648 static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, char *origtime, char *filename)
03649 {
03650 int res = 0;
03651 struct vm_zone *the_zone = NULL;
03652 time_t t;
03653 long tin;
03654
03655 if (sscanf(origtime,"%ld",&tin) < 1) {
03656 ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
03657 return 0;
03658 }
03659 t = tin;
03660
03661
03662 if (!ast_strlen_zero(vmu->zonetag)) {
03663
03664 struct vm_zone *z;
03665 z = zones;
03666 while (z) {
03667 if (!strcmp(z->name, vmu->zonetag)) {
03668 the_zone = z;
03669 break;
03670 }
03671 z = z->next;
03672 }
03673 }
03674
03675
03676 #if 0
03677
03678 localtime_r(&t, &time_now);
03679 tv_now = ast_tvnow();
03680 tnow = tv_now.tv_sec;
03681 localtime_r(&tnow,&time_then);
03682
03683
03684 if (time_now.tm_year == time_then.tm_year)
03685 snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
03686 else
03687 snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
03688 pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
03689
03690
03691 #endif
03692 if (the_zone)
03693 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
03694 else if(!strcasecmp(chan->language,"se"))
03695 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
03696 else if(!strcasecmp(chan->language,"no"))
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,"de"))
03699 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
03700 else if (!strcasecmp(chan->language,"nl"))
03701 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
03702 else if (!strcasecmp(chan->language,"he"))
03703 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' HM", NULL);
03704 else if (!strcasecmp(chan->language,"it"))
03705 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);
03706 else if (!strcasecmp(chan->language,"gr"))
03707 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
03708 else if (!strcasecmp(chan->language,"pt_BR"))
03709 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);
03710 else
03711 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
03712 #if 0
03713 pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
03714 #endif
03715 return res;
03716 }
03717
03718
03719
03720 static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, char *context, int callback)
03721 {
03722 int res = 0;
03723 int i;
03724 char *callerid, *name;
03725 char prefile[256]="";
03726
03727
03728
03729
03730 if ((cid == NULL)||(context == NULL))
03731 return res;
03732
03733
03734 ast_log(LOG_DEBUG, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
03735 ast_callerid_parse(cid, &name, &callerid);
03736 if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
03737
03738
03739 for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
03740 ast_log(LOG_DEBUG, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
03741 if ((strcmp(cidinternalcontexts[i], context) == 0))
03742 break;
03743 }
03744 if (i != MAX_NUM_CID_CONTEXTS){
03745 if (!res) {
03746 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
03747 if (!ast_strlen_zero(prefile)) {
03748
03749 if (ast_fileexists(prefile, NULL, NULL) > 0) {
03750 if (option_verbose > 2)
03751 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
03752 if (!callback)
03753 res = wait_file2(chan, vms, "vm-from");
03754 res = ast_streamfile(chan, prefile, chan->language) > -1;
03755 res = ast_waitstream(chan, "");
03756 } else {
03757 if (option_verbose > 2)
03758 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: message from '%s'\n", callerid);
03759
03760 if (!callback)
03761 res = wait_file2(chan, vms, "vm-from-extension");
03762 res = ast_say_digit_str(chan, callerid, "", chan->language);
03763 }
03764 }
03765 }
03766 }
03767
03768 else if (!res){
03769 ast_log(LOG_DEBUG, "VM-CID: Numeric caller id: (%s)\n",callerid);
03770
03771 if (!callback)
03772 res = wait_file2(chan, vms, "vm-from-phonenumber");
03773 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
03774 }
03775 } else {
03776
03777 ast_log(LOG_DEBUG, "VM-CID: From an unknown number\n");
03778
03779 res = wait_file2(chan, vms, "vm-unknown-caller");
03780 }
03781 return res;
03782 }
03783
03784 static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, char *duration, int minduration)
03785 {
03786 int res = 0;
03787 int durationm;
03788 int durations;
03789
03790 if((duration == NULL))
03791 return res;
03792
03793
03794 durations=atoi(duration);
03795 durationm=(durations / 60);
03796
03797 ast_log(LOG_DEBUG, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
03798
03799 if((!res)&&(durationm>=minduration)) {
03800 res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, (char *) NULL);
03801 res = wait_file2(chan, vms, "vm-minutes");
03802 }
03803 return res;
03804 }
03805
03806 static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
03807 {
03808 int res = 0;
03809 char filename[256],*origtime, *cid, *context, *duration;
03810 char *category;
03811 struct ast_config *msg_cfg;
03812
03813 vms->starting = 0;
03814 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
03815 adsi_message(chan, vms);
03816 if (!vms->curmsg)
03817 res = wait_file2(chan, vms, "vm-first");
03818 else if (vms->curmsg == vms->lastmsg)
03819 res = wait_file2(chan, vms, "vm-last");
03820 if (!res) {
03821 if (!strcasecmp(chan->language, "se")) {
03822 res = wait_file2(chan, vms, "vm-meddelandet");
03823 }
03824 else {
03825 res = wait_file2(chan, vms, "vm-message");
03826 }
03827 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
03828 if (!res)
03829 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
03830 }
03831 }
03832
03833
03834 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
03835 snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
03836 RETRIEVE(vms->curdir, vms->curmsg);
03837 msg_cfg = ast_config_load(filename);
03838 if (!msg_cfg) {
03839 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
03840 return 0;
03841 }
03842
03843 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
03844 ast_log(LOG_WARNING, "No origtime?!\n");
03845 DISPOSE(vms->curdir, vms->curmsg);
03846 ast_config_destroy(msg_cfg);
03847 return 0;
03848 }
03849
03850 cid = ast_variable_retrieve(msg_cfg, "message", "callerid");
03851 duration = ast_variable_retrieve(msg_cfg, "message", "duration");
03852 category = ast_variable_retrieve(msg_cfg, "message", "category");
03853
03854 context = ast_variable_retrieve(msg_cfg, "message", "context");
03855 if (!strncasecmp("macro",context,5))
03856 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
03857
03858 if (!res)
03859 res = play_message_category(chan, category);
03860 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
03861 res = play_message_datetime(chan, vmu, origtime, filename);
03862 if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
03863 res = play_message_callerid(chan, vms, cid, context, 0);
03864 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
03865 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
03866
03867 if (res == '1')
03868 res = 0;
03869 ast_config_destroy(msg_cfg);
03870
03871 if (!res) {
03872 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
03873 vms->heard[vms->curmsg] = 1;
03874 res = wait_file(chan, vms, vms->fn);
03875 }
03876 DISPOSE(vms->curdir, vms->curmsg);
03877 return res;
03878 }
03879
03880 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box)
03881 {
03882 int res = 0;
03883 int count_msg, last_msg;
03884
03885 ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
03886
03887
03888
03889
03890 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
03891
03892 make_dir(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
03893 count_msg = count_messages(vmu, vms->curdir);
03894 if (count_msg < 0)
03895 return count_msg;
03896 else
03897 vms->lastmsg = count_msg - 1;
03898
03899
03900
03901
03902
03903
03904
03905
03906 last_msg = last_message_index(vmu, vms->curdir);
03907 if (last_msg < 0)
03908 return last_msg;
03909 else if(vms->lastmsg != last_msg)
03910 {
03911 ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir);
03912 res = resequence_mailbox(vmu, vms->curdir);
03913 if (res)
03914 return res;
03915 }
03916
03917 return 0;
03918 }
03919
03920 static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
03921 {
03922 int x, nummsg;
03923 int res = 0;
03924
03925 if (vms->lastmsg <= -1)
03926 goto done;
03927
03928
03929 if (vm_lock_path(vms->curdir))
03930 return ERROR_LOCK_PATH;
03931
03932 vms->curmsg = -1;
03933 for (x = 0; x < vmu->maxmsg; x++) {
03934 if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) {
03935
03936 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
03937 if (!EXISTS(vms->curdir, x, vms->fn, NULL))
03938 break;
03939 vms->curmsg++;
03940 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
03941 if (strcmp(vms->fn, vms->fn2)) {
03942 RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
03943 }
03944 } else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) {
03945
03946 res = save_to_folder(vmu, vms->curdir, x, vmu->context, vms->username, 1);
03947 if (res == ERROR_LOCK_PATH) {
03948
03949 vms->deleted[x] = 0;
03950 vms->heard[x] = 0;
03951 --x;
03952 }
03953 }
03954 }
03955
03956
03957 nummsg = x - 1;
03958 for (x = vms->curmsg + 1; x <= nummsg; x++) {
03959 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
03960 if (EXISTS(vms->curdir, x, vms->fn, NULL))
03961 DELETE(vms->curdir, x, vms->fn);
03962 }
03963 ast_unlock_path(vms->curdir);
03964
03965 done:
03966 if (vms->deleted)
03967 memset(vms->deleted, 0, vmu->maxmsg * sizeof(int));
03968 if (vms->heard)
03969 memset(vms->heard, 0, vmu->maxmsg * sizeof(int));
03970
03971 return 0;
03972 }
03973
03974
03975
03976
03977
03978
03979
03980 static int vm_play_folder_name_gr(struct ast_channel *chan, char *mbox)
03981 {
03982 int cmd;
03983 char *buf;
03984
03985 buf = alloca(strlen(mbox)+2);
03986 strcpy(buf, mbox);
03987 strcat(buf,"s");
03988
03989 if (!strcasecmp(mbox, "vm-INBOX") || !strcasecmp(mbox, "vm-Old")){
03990 cmd = ast_play_and_wait(chan, buf);
03991 if (cmd)
03992 return cmd;
03993 return ast_play_and_wait(chan, "vm-messages");
03994 } else {
03995 cmd = ast_play_and_wait(chan, "vm-messages");
03996 if (cmd)
03997 return cmd;
03998 return ast_play_and_wait(chan, mbox);
03999 }
04000 }
04001
04002 static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
04003 {
04004 int cmd;
04005
04006 if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "fr") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {
04007 cmd = ast_play_and_wait(chan, "vm-messages");
04008 if (cmd)
04009 return cmd;
04010 return ast_play_and_wait(chan, mbox);
04011 } else if (!strcasecmp(chan->language, "gr")){
04012 return vm_play_folder_name_gr(chan, mbox);
04013 } else {
04014 cmd = ast_play_and_wait(chan, mbox);
04015 if (cmd)
04016 return cmd;
04017 return ast_play_and_wait(chan, "vm-messages");
04018 }
04019 }
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033 static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
04034 {
04035 int res = 0;
04036
04037 if (vms->newmessages) {
04038 res = ast_play_and_wait(chan, "vm-youhave");
04039 if (!res)
04040 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
04041 if (!res) {
04042 if ((vms->newmessages == 1)) {
04043 res = ast_play_and_wait(chan, "vm-INBOX");
04044 if (!res)
04045 res = ast_play_and_wait(chan, "vm-message");
04046 } else {
04047 res = ast_play_and_wait(chan, "vm-INBOXs");
04048 if (!res)
04049 res = ast_play_and_wait(chan, "vm-messages");
04050 }
04051 }
04052 } else if (vms->oldmessages){
04053 res = ast_play_and_wait(chan, "vm-youhave");
04054 if (!res)
04055 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
04056 if ((vms->oldmessages == 1)){
04057 res = ast_play_and_wait(chan, "vm-Old");
04058 if (!res)
04059 res = ast_play_and_wait(chan, "vm-message");
04060 } else {
04061 res = ast_play_and_wait(chan, "vm-Olds");
04062 if (!res)
04063 res = ast_play_and_wait(chan, "vm-messages");
04064 }
04065 } else if (!vms->oldmessages && !vms->newmessages)
04066 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
04067 return res;
04068 }
04069
04070
04071 static int vm_intro_en(struct ast_channel *chan,struct vm_state *vms)
04072 {
04073
04074 int res;
04075 res = ast_play_and_wait(chan, "vm-youhave");
04076 if (!res) {
04077 if (vms->newmessages) {
04078 res = say_and_wait(chan, vms->newmessages, chan->language);
04079 if (!res)
04080 res = ast_play_and_wait(chan, "vm-INBOX");
04081 if (vms->oldmessages && !res)
04082 res = ast_play_and_wait(chan, "vm-and");
04083 else if (!res) {
04084 if ((vms->newmessages == 1))
04085 res = ast_play_and_wait(chan, "vm-message");
04086 else
04087 res = ast_play_and_wait(chan, "vm-messages");
04088 }
04089
04090 }
04091 if (!res && vms->oldmessages) {
04092 res = say_and_wait(chan, vms->oldmessages, chan->language);
04093 if (!res)
04094 res = ast_play_and_wait(chan, "vm-Old");
04095 if (!res) {
04096 if (vms->oldmessages == 1)
04097 res = ast_play_and_wait(chan, "vm-message");
04098 else
04099 res = ast_play_and_wait(chan, "vm-messages");
04100 }
04101 }
04102 if (!res) {
04103 if (!vms->oldmessages && !vms->newmessages) {
04104 res = ast_play_and_wait(chan, "vm-no");
04105 if (!res)
04106 res = ast_play_and_wait(chan, "vm-messages");
04107 }
04108 }
04109 }
04110 return res;
04111 }
04112
04113
04114 static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
04115 {
04116
04117 int res;
04118 if (!vms->oldmessages && !vms->newmessages)
04119 res = ast_play_and_wait(chan, "vm-no") ||
04120 ast_play_and_wait(chan, "vm-message");
04121 else
04122 res = ast_play_and_wait(chan, "vm-youhave");
04123 if (!res && vms->newmessages) {
04124 res = (vms->newmessages == 1) ?
04125 ast_play_and_wait(chan, "digits/un") ||
04126 ast_play_and_wait(chan, "vm-nuovo") ||
04127 ast_play_and_wait(chan, "vm-message") :
04128
04129 say_and_wait(chan, vms->newmessages, chan->language) ||
04130 ast_play_and_wait(chan, "vm-nuovi") ||
04131 ast_play_and_wait(chan, "vm-messages");
04132 if (!res && vms->oldmessages)
04133 res = ast_play_and_wait(chan, "vm-and");
04134 }
04135 if (!res && vms->oldmessages) {
04136 res = (vms->oldmessages == 1) ?
04137 ast_play_and_wait(chan, "digits/un") ||
04138 ast_play_and_wait(chan, "vm-vecchio") ||
04139 ast_play_and_wait(chan, "vm-message") :
04140
04141 say_and_wait(chan, vms->oldmessages, chan->language) ||
04142 ast_play_and_wait(chan, "vm-vecchi") ||
04143 ast_play_and_wait(chan, "vm-messages");
04144 }
04145 return res;
04146 }
04147
04148
04149 static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
04150 {
04151
04152 int res;
04153
04154 res = ast_play_and_wait(chan, "vm-youhave");
04155 if (res)
04156 return res;
04157
04158 if (!vms->oldmessages && !vms->newmessages) {
04159 res = ast_play_and_wait(chan, "vm-no");
04160 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04161 return res;
04162 }
04163
04164 if (vms->newmessages) {
04165 if ((vms->newmessages == 1)) {
04166 res = ast_play_and_wait(chan, "digits/ett");
04167 res = res ? res : ast_play_and_wait(chan, "vm-nytt");
04168 res = res ? res : ast_play_and_wait(chan, "vm-message");
04169 } else {
04170 res = say_and_wait(chan, vms->newmessages, chan->language);
04171 res = res ? res : ast_play_and_wait(chan, "vm-nya");
04172 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04173 }
04174 if (!res && vms->oldmessages)
04175 res = ast_play_and_wait(chan, "vm-and");
04176 }
04177 if (!res && vms->oldmessages) {
04178 if (vms->oldmessages == 1) {
04179 res = ast_play_and_wait(chan, "digits/ett");
04180 res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
04181 res = res ? res : ast_play_and_wait(chan, "vm-message");
04182 } else {
04183 res = say_and_wait(chan, vms->oldmessages, chan->language);
04184 res = res ? res : ast_play_and_wait(chan, "vm-gamla");
04185 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04186 }
04187 }
04188
04189 return res;
04190 }
04191
04192
04193 static int vm_intro_no(struct ast_channel *chan,struct vm_state *vms)
04194 {
04195
04196 int res;
04197
04198 res = ast_play_and_wait(chan, "vm-youhave");
04199 if (res)
04200 return res;
04201
04202 if (!vms->oldmessages && !vms->newmessages) {
04203 res = ast_play_and_wait(chan, "vm-no");
04204 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04205 return res;
04206 }
04207
04208 if (vms->newmessages) {
04209 if ((vms->newmessages == 1)) {
04210 res = ast_play_and_wait(chan, "digits/1");
04211 res = res ? res : ast_play_and_wait(chan, "vm-ny");
04212 res = res ? res : ast_play_and_wait(chan, "vm-message");
04213 } else {
04214 res = say_and_wait(chan, vms->newmessages, chan->language);
04215 res = res ? res : ast_play_and_wait(chan, "vm-nye");
04216 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04217 }
04218 if (!res && vms->oldmessages)
04219 res = ast_play_and_wait(chan, "vm-and");
04220 }
04221 if (!res && vms->oldmessages) {
04222 if (vms->oldmessages == 1) {
04223 res = ast_play_and_wait(chan, "digits/1");
04224 res = res ? res : ast_play_and_wait(chan, "vm-gamel");
04225 res = res ? res : ast_play_and_wait(chan, "vm-message");
04226 } else {
04227 res = say_and_wait(chan, vms->oldmessages, chan->language);
04228 res = res ? res : ast_play_and_wait(chan, "vm-gamle");
04229 res = res ? res : ast_play_and_wait(chan, "vm-messages");
04230 }
04231 }
04232
04233 return res;
04234 }
04235
04236
04237 static int vm_intro_de(struct ast_channel *chan,struct vm_state *vms)
04238 {
04239
04240 int res;
04241 res = ast_play_and_wait(chan, "vm-youhave");
04242 if (!res) {
04243 if (vms->newmessages) {
04244 if ((vms->newmessages == 1))
04245 res = ast_play_and_wait(chan, "digits/1F");
04246 else
04247 res = say_and_wait(chan, vms->newmessages, chan->language);
04248 if (!res)
04249 res = ast_play_and_wait(chan, "vm-INBOX");
04250 if (vms->oldmessages && !res)
04251 res = ast_play_and_wait(chan, "vm-and");
04252 else if (!res) {
04253 if ((vms->newmessages == 1))
04254 res = ast_play_and_wait(chan, "vm-message");
04255 else
04256 res = ast_play_and_wait(chan, "vm-messages");
04257 }
04258
04259 }
04260 if (!res && vms->oldmessages) {
04261 if (vms->oldmessages == 1)
04262 res = ast_play_and_wait(chan, "digits/1F");
04263 else
04264 res = say_and_wait(chan, vms->oldmessages, chan->language);
04265 if (!res)
04266 res = ast_play_and_wait(chan, "vm-Old");
04267 if (!res) {
04268 if (vms->oldmessages == 1)
04269 res = ast_play_and_wait(chan, "vm-message");
04270 else
04271 res = ast_play_and_wait(chan, "vm-messages");
04272 }
04273 }
04274 if (!res) {
04275 if (!vms->oldmessages && !vms->newmessages) {
04276 res = ast_play_and_wait(chan, "vm-no");
04277 if (!res)
04278 res = ast_play_and_wait(chan, "vm-messages");
04279 }
04280 }
04281 }
04282 return res;
04283 }
04284
04285
04286 static int vm_intro_es(struct ast_channel *chan,struct vm_state *vms)
04287 {
04288
04289 int res;
04290 if (!vms->oldmessages && !vms->newmessages) {
04291 res = ast_play_and_wait(chan, "vm-youhaveno");
04292 if (!res)
04293 res = ast_play_and_wait(chan, "vm-messages");
04294 } else {
04295 res = ast_play_and_wait(chan, "vm-youhave");
04296 }
04297 if (!res) {
04298 if (vms->newmessages) {
04299 if (!res) {
04300 if ((vms->newmessages == 1)) {
04301 res = ast_play_and_wait(chan, "digits/1M");
04302 if (!res)
04303 res = ast_play_and_wait(chan, "vm-message");
04304 if (!res)
04305 res = ast_play_and_wait(chan, "vm-INBOXs");
04306 } else {
04307 res = say_and_wait(chan, vms->newmessages, chan->language);
04308 if (!res)
04309 res = ast_play_and_wait(chan, "vm-messages");
04310 if (!res)
04311 res = ast_play_and_wait(chan, "vm-INBOX");
04312 }
04313 }
04314 if (vms->oldmessages && !res)
04315 res = ast_play_and_wait(chan, "vm-and");
04316 }
04317 if (vms->oldmessages) {
04318 if (!res) {
04319 if (vms->oldmessages == 1) {
04320 res = ast_play_and_wait(chan, "digits/1M");
04321 if (!res)
04322 res = ast_play_and_wait(chan, "vm-message");
04323 if (!res)
04324 res = ast_play_and_wait(chan, "vm-Olds");
04325 } else {
04326 res = say_and_wait(chan, vms->oldmessages, chan->language);
04327 if (!res)
04328 res = ast_play_and_wait(chan, "vm-messages");
04329 if (!res)
04330 res = ast_play_and_wait(chan, "vm-Old");
04331 }
04332 }
04333 }
04334 }
04335 return res;
04336 }
04337
04338
04339 static int vm_intro_pt_BR(struct ast_channel *chan,struct vm_state *vms) {
04340
04341 int res;
04342 if (!vms->oldmessages && !vms->newmessages) {
04343 res = ast_play_and_wait(chan, "vm-nomessages");
04344 return res;
04345 }
04346 else {
04347 res = ast_play_and_wait(chan, "vm-youhave");
04348 }
04349 if (vms->newmessages) {
04350 if (!res)
04351 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
04352 if ((vms->newmessages == 1)) {
04353 if (!res)
04354 res = ast_play_and_wait(chan, "vm-message");
04355 if (!res)
04356 res = ast_play_and_wait(chan, "vm-INBOXs");
04357 }
04358 else {
04359 if (!res)
04360 res = ast_play_and_wait(chan, "vm-messages");
04361 if (!res)
04362 res = ast_play_and_wait(chan, "vm-INBOX");
04363 }
04364 if (vms->oldmessages && !res)
04365 res = ast_play_and_wait(chan, "vm-and");
04366 }
04367 if (vms->oldmessages) {
04368 if (!res)
04369 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
04370 if (vms->oldmessages == 1) {
04371 if (!res)
04372 res = ast_play_and_wait(chan, "vm-message");
04373 if (!res)
04374 res = ast_play_and_wait(chan, "vm-Olds");
04375 }
04376 else {
04377 if (!res)
04378 res = ast_play_and_wait(chan, "vm-messages");
04379 if (!res)
04380 res = ast_play_and_wait(chan, "vm-Old");
04381 }
04382 }
04383 return res;
04384 }
04385
04386
04387 static int vm_intro_fr(struct ast_channel *chan,struct vm_state *vms)
04388 {
04389
04390 int res;
04391 res = ast_play_and_wait(chan, "vm-youhave");
04392 if (!res) {
04393 if (vms->newmessages) {
04394 res = say_and_wait(chan, vms->newmessages, chan->language);
04395 if (!res)
04396 res = ast_play_and_wait(chan, "vm-INBOX");
04397 if (vms->oldmessages && !res)
04398 res = ast_play_and_wait(chan, "vm-and");
04399 else if (!res) {
04400 if ((vms->newmessages == 1))
04401 res = ast_play_and_wait(chan, "vm-message");
04402 else
04403 res = ast_play_and_wait(chan, "vm-messages");
04404 }
04405
04406 }
04407 if (!res && vms->oldmessages) {
04408 res = say_and_wait(chan, vms->oldmessages, chan->language);
04409 if (!res) {
04410 if (vms->oldmessages == 1)
04411 res = ast_play_and_wait(chan, "vm-message");
04412 else
04413 res = ast_play_and_wait(chan, "vm-messages");
04414 }
04415 if (!res)
04416 res = ast_play_and_wait(chan, "vm-Old");
04417 }
04418 if (!res) {
04419 if (!vms->oldmessages && !vms->newmessages) {
04420 res = ast_play_and_wait(chan, "vm-no");
04421 if (!res)
04422 res = ast_play_and_wait(chan, "vm-messages");
04423 }
04424 }
04425 }
04426 return res;
04427 }
04428
04429
04430 static int vm_intro_nl(struct ast_channel *chan,struct vm_state *vms)
04431 {
04432
04433 int res;
04434 res = ast_play_and_wait(chan, "vm-youhave");
04435 if (!res) {
04436 if (vms->newmessages) {
04437 res = say_and_wait(chan, vms->newmessages, chan->language);
04438 if (!res) {
04439 if (vms->newmessages == 1)
04440 res = ast_play_and_wait(chan, "vm-INBOXs");
04441 else
04442 res = ast_play_and_wait(chan, "vm-INBOX");
04443 }
04444 if (vms->oldmessages && !res)
04445 res = ast_play_and_wait(chan, "vm-and");
04446 else if (!res) {
04447 if ((vms->newmessages == 1))
04448 res = ast_play_and_wait(chan, "vm-message");
04449 else
04450 res = ast_play_and_wait(chan, "vm-messages");
04451 }
04452
04453 }
04454 if (!res && vms->oldmessages) {
04455 res = say_and_wait(chan, vms->oldmessages, chan->language);
04456 if (!res) {
04457 if (vms->oldmessages == 1)
04458 res = ast_play_and_wait(chan, "vm-Olds");
04459 else
04460 res = ast_play_and_wait(chan, "vm-Old");
04461 }
04462 if (!res) {
04463 if (vms->oldmessages == 1)
04464 res = ast_play_and_wait(chan, "vm-message");
04465 else
04466 res = ast_play_and_wait(chan, "vm-messages");
04467 }
04468 }
04469 if (!res) {
04470 if (!vms->oldmessages && !vms->newmessages) {
04471 res = ast_play_and_wait(chan, "vm-no");
04472 if (!res)
04473 res = ast_play_and_wait(chan, "vm-messages");
04474 }
04475 }
04476 }
04477 return res;
04478 }
04479
04480
04481 static int vm_intro_pt(struct ast_channel *chan,struct vm_state *vms)
04482 {
04483
04484 int res;
04485 res = ast_play_and_wait(chan, "vm-youhave");
04486 if (!res) {
04487 if (vms->newmessages) {
04488 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
04489 if (!res) {
04490 if ((vms->newmessages == 1)) {
04491 res = ast_play_and_wait(chan, "vm-message");
04492 if (!res)
04493 res = ast_play_and_wait(chan, "vm-INBOXs");
04494 } else {
04495 res = ast_play_and_wait(chan, "vm-messages");
04496 if (!res)
04497 res = ast_play_and_wait(chan, "vm-INBOX");
04498 }
04499 }
04500 if (vms->oldmessages && !res)
04501 res = ast_play_and_wait(chan, "vm-and");
04502 }
04503 if (!res && vms->oldmessages) {
04504 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
04505 if (!res) {
04506 if (vms->oldmessages == 1) {
04507 res = ast_play_and_wait(chan, "vm-message");
04508 if (!res)
04509 res = ast_play_and_wait(chan, "vm-Olds");
04510 } else {
04511 res = ast_play_and_wait(chan, "vm-messages");
04512 if (!res)
04513 res = ast_play_and_wait(chan, "vm-Old");
04514 }
04515 }
04516 }
04517 if (!res) {
04518 if (!vms->oldmessages && !vms->newmessages) {
04519 res = ast_play_and_wait(chan, "vm-no");
04520 if (!res)
04521 res = ast_play_and_wait(chan, "vm-messages");
04522 }
04523 }
04524 }
04525 return res;
04526 }
04527
04528
04529
04530
04531
04532
04533
04534
04535
04536
04537
04538
04539
04540
04541
04542
04543
04544 static int vm_intro_cz(struct ast_channel *chan,struct vm_state *vms)
04545 {
04546 int res;
04547 res = ast_play_and_wait(chan, "vm-youhave");
04548 if (!res) {
04549 if (vms->newmessages) {
04550 if (vms->newmessages == 1) {
04551 res = ast_play_and_wait(chan, "digits/jednu");
04552 } else {
04553 res = say_and_wait(chan, vms->newmessages, chan->language);
04554 }
04555 if (!res) {
04556 if ((vms->newmessages == 1))
04557 res = ast_play_and_wait(chan, "vm-novou");
04558 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
04559 res = ast_play_and_wait(chan, "vm-nove");
04560 if (vms->newmessages > 4)
04561 res = ast_play_and_wait(chan, "vm-novych");
04562 }
04563 if (vms->oldmessages && !res)
04564 res = ast_play_and_wait(chan, "vm-and");
04565 else if (!res) {
04566 if ((vms->newmessages == 1))
04567 res = ast_play_and_wait(chan, "vm-zpravu");
04568 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
04569 res = ast_play_and_wait(chan, "vm-zpravy");
04570 if (vms->newmessages > 4)
04571 res = ast_play_and_wait(chan, "vm-zprav");
04572 }
04573 }
04574 if (!res && vms->oldmessages) {
04575 res = say_and_wait(chan, vms->oldmessages, chan->language);
04576 if (!res) {
04577 if ((vms->oldmessages == 1))
04578 res = ast_play_and_wait(chan, "vm-starou");
04579 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
04580 res = ast_play_and_wait(chan, "vm-stare");
04581 if (vms->oldmessages > 4)
04582 res = ast_play_and_wait(chan, "vm-starych");
04583 }
04584 if (!res) {
04585 if ((vms->oldmessages == 1))
04586 res = ast_play_and_wait(chan, "vm-zpravu");
04587 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
04588 res = ast_play_and_wait(chan, "vm-zpravy");
04589 if (vms->oldmessages > 4)
04590 res = ast_play_and_wait(chan, "vm-zprav");
04591 }
04592 }
04593 if (!res) {
04594 if (!vms->oldmessages && !vms->newmessages) {
04595 res = ast_play_and_wait(chan, "vm-no");
04596 if (!res)
04597 res = ast_play_and_wait(chan, "vm-zpravy");
04598 }
04599 }
04600 }
04601 return res;
04602 }
04603
04604 static int vm_intro(struct ast_channel *chan,struct vm_state *vms)
04605 {
04606
04607 if (!strcasecmp(chan->language, "de")) {
04608 return vm_intro_de(chan, vms);
04609 } else if (!strcasecmp(chan->language, "es")) {
04610 return vm_intro_es(chan, vms);
04611 } else if (!strcasecmp(chan->language, "it")) {
04612 return vm_intro_it(chan, vms);
04613 } else if (!strcasecmp(chan->language, "fr")) {
04614 return vm_intro_fr(chan, vms);
04615 } else if (!strcasecmp(chan->language, "nl")) {
04616 return vm_intro_nl(chan, vms);
04617 } else if (!strcasecmp(chan->language, "pt")) {
04618 return vm_intro_pt(chan, vms);
04619 } else if (!strcasecmp(chan->language, "pt_BR")) {
04620 return vm_intro_pt_BR(chan, vms);
04621 } else if (!strcasecmp(chan->language, "cz")) {
04622 return vm_intro_cz(chan, vms);
04623 } else if (!strcasecmp(chan->language, "gr")) {
04624 return vm_intro_gr(chan, vms);
04625 } else if (!strcasecmp(chan->language, "se")) {
04626 return vm_intro_se(chan, vms);
04627 } else if (!strcasecmp(chan->language, "no")) {
04628 return vm_intro_no(chan, vms);
04629 } else {
04630 return vm_intro_en(chan, vms);
04631 }
04632 }
04633
04634 static int vm_instructions(struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
04635 {
04636 int res = 0;
04637
04638 while (!res) {
04639 if (vms->starting) {
04640 if (vms->lastmsg > -1) {
04641 res = ast_play_and_wait(chan, "vm-onefor");
04642 if (!res)
04643 res = vm_play_folder_name(chan, vms->vmbox);
04644 }
04645 if (!res)
04646 res = ast_play_and_wait(chan, "vm-opts");
04647 } else {
04648 if (vms->curmsg)
04649 res = ast_play_and_wait(chan, "vm-prev");
04650 if (!res && !skipadvanced)
04651 res = ast_play_and_wait(chan, "vm-advopts");
04652 if (!res)
04653 res = ast_play_and_wait(chan, "vm-repeat");
04654 if (!res && (vms->curmsg != vms->lastmsg))
04655 res = ast_play_and_wait(chan, "vm-next");
04656 if (!res) {
04657 if (!vms->deleted[vms->curmsg])
04658 res = ast_play_and_wait(chan, "vm-delete");
04659 else
04660 res = ast_play_and_wait(chan, "vm-undelete");
04661 if (!res)
04662 res = ast_play_and_wait(chan, "vm-toforward");
04663 if (!res)
04664 res = ast_play_and_wait(chan, "vm-savemessage");
04665 }
04666 }
04667 if (!res)
04668 res = ast_play_and_wait(chan, "vm-helpexit");
04669 if (!res)
04670 res = ast_waitfordigit(chan, 6000);
04671 if (!res) {
04672 vms->repeats++;
04673 if (vms->repeats > 2) {
04674 res = 't';
04675 }
04676 }
04677 }
04678 return res;
04679 }
04680
04681 static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04682 {
04683 int cmd = 0;
04684 int duration = 0;
04685 int tries = 0;
04686 char newpassword[80] = "";
04687 char newpassword2[80] = "";
04688 char prefile[256]="";
04689 unsigned char buf[256];
04690 int bytes=0;
04691
04692 if (adsi_available(chan)) {
04693 bytes += adsi_logo(buf + bytes);
04694 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
04695 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04696 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04697 bytes += adsi_voice_mode(buf + bytes, 0);
04698 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04699 }
04700
04701
04702
04703 for (;;) {
04704 newpassword[1] = '\0';
04705 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
04706 if (cmd == '#')
04707 newpassword[0] = '\0';
04708 if (cmd < 0 || cmd == 't' || cmd == '#')
04709 return cmd;
04710 cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
04711 if (cmd < 0 || cmd == 't' || cmd == '#')
04712 return cmd;
04713 newpassword2[1] = '\0';
04714 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
04715 if (cmd == '#')
04716 newpassword2[0] = '\0';
04717 if (cmd < 0 || cmd == 't' || cmd == '#')
04718 return cmd;
04719 cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#");
04720 if (cmd < 0 || cmd == 't' || cmd == '#')
04721 return cmd;
04722 if (!strcmp(newpassword, newpassword2))
04723 break;
04724 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
04725 cmd = ast_play_and_wait(chan, "vm-mismatch");
04726 if (++tries == 3)
04727 return -1;
04728 }
04729 if (ast_strlen_zero(ext_pass_cmd))
04730 vm_change_password(vmu,newpassword);
04731 else
04732 vm_change_password_shell(vmu,newpassword);
04733
04734 cmd = ast_play_and_wait(chan,"vm-passchanged");
04735
04736
04737 if (ast_test_flag(vmu, VM_FORCENAME)) {
04738 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
04739 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04740 if (cmd < 0 || cmd == 't' || cmd == '#')
04741 return cmd;
04742 }
04743
04744
04745 if (ast_test_flag(vmu, VM_FORCEGREET)) {
04746 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
04747 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04748 if (cmd < 0 || cmd == 't' || cmd == '#')
04749 return cmd;
04750 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
04751 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04752 if (cmd < 0 || cmd == 't' || cmd == '#')
04753 return cmd;
04754 }
04755
04756 return cmd;
04757 }
04758
04759 static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04760 {
04761 int cmd = 0;
04762 int retries = 0;
04763 int duration = 0;
04764 char newpassword[80] = "";
04765 char newpassword2[80] = "";
04766 char prefile[256]="";
04767 unsigned char buf[256];
04768 int bytes=0;
04769
04770 if (adsi_available(chan))
04771 {
04772 bytes += adsi_logo(buf + bytes);
04773 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
04774 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04775 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04776 bytes += adsi_voice_mode(buf + bytes, 0);
04777 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04778 }
04779 while ((cmd >= 0) && (cmd != 't')) {
04780 if (cmd)
04781 retries = 0;
04782 switch (cmd) {
04783 case '1':
04784 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
04785 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04786 break;
04787 case '2':
04788 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
04789 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04790 break;
04791 case '3':
04792 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
04793 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04794 break;
04795 case '4':
04796 cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
04797 break;
04798 case '5':
04799 if (vmu->password[0] == '-') {
04800 cmd = ast_play_and_wait(chan, "vm-no");
04801 break;
04802 }
04803 newpassword[1] = '\0';
04804 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
04805 if (cmd == '#')
04806 newpassword[0] = '\0';
04807 else {
04808 if (cmd < 0)
04809 break;
04810 if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
04811 break;
04812 }
04813 }
04814 newpassword2[1] = '\0';
04815 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
04816 if (cmd == '#')
04817 newpassword2[0] = '\0';
04818 else {
04819 if (cmd < 0)
04820 break;
04821
04822 if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#"))) {
04823 break;
04824 }
04825 }
04826 if (strcmp(newpassword, newpassword2)) {
04827 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
04828 cmd = ast_play_and_wait(chan, "vm-mismatch");
04829 break;
04830 }
04831 if (ast_strlen_zero(ext_pass_cmd))
04832 vm_change_password(vmu,newpassword);
04833 else
04834 vm_change_password_shell(vmu,newpassword);
04835 ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
04836 cmd = ast_play_and_wait(chan,"vm-passchanged");
04837 break;
04838 case '*':
04839 cmd = 't';
04840 break;
04841 default:
04842 cmd = ast_play_and_wait(chan,"vm-options");
04843 if (!cmd)
04844 cmd = ast_waitfordigit(chan,6000);
04845 if (!cmd)
04846 retries++;
04847 if (retries > 3)
04848 cmd = 't';
04849 }
04850 }
04851 if (cmd == 't')
04852 cmd = 0;
04853 return cmd;
04854 }
04855
04856 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
04857 {
04858 int cmd = 0;
04859 int retries = 0;
04860 int duration = 0;
04861 char prefile[256]="";
04862 unsigned char buf[256];
04863 int bytes=0;
04864
04865 if (adsi_available(chan))
04866 {
04867 bytes += adsi_logo(buf + bytes);
04868 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
04869 bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
04870 bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
04871 bytes += adsi_voice_mode(buf + bytes, 0);
04872 adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
04873 }
04874 snprintf(prefile,sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
04875 while((cmd >= 0) && (cmd != 't')) {
04876 if (cmd)
04877 retries = 0;
04878 RETRIEVE(prefile, -1);
04879 if (ast_fileexists(prefile, NULL, NULL) > 0) {
04880 switch (cmd) {
04881 case '1':
04882 cmd = play_record_review(chan,"vm-rec-temp",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04883 break;
04884 case '2':
04885 DELETE(prefile, -1, prefile);
04886 ast_play_and_wait(chan,"vm-tempremoved");
04887 cmd = 't';
04888 break;
04889 case '*':
04890 cmd = 't';
04891 break;
04892 default:
04893 if (ast_fileexists(prefile, NULL, NULL) > 0) {
04894 cmd = ast_play_and_wait(chan,"vm-tempgreeting2");
04895 } else {
04896 cmd = ast_play_and_wait(chan,"vm-tempgreeting");
04897 } if (!cmd) {
04898 cmd = ast_waitfordigit(chan,6000);
04899 } if (!cmd) {
04900 retries++;
04901 } if (retries > 3) {
04902 cmd = 't';
04903 }
04904 }
04905 } else {
04906 play_record_review(chan,"vm-rec-temp",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain);
04907 cmd = 't';
04908 }
04909 DISPOSE(prefile, -1);
04910 }
04911 if (cmd == 't')
04912 cmd = 0;
04913 return cmd;
04914 }
04915
04916
04917
04918 static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04919 {
04920 int cmd=0;
04921
04922 if (vms->lastmsg > -1) {
04923 cmd = play_message(chan, vmu, vms);
04924 } else {
04925 cmd = ast_play_and_wait(chan, "vm-youhaveno");
04926 if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
04927 if (!cmd) {
04928 snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
04929 cmd = ast_play_and_wait(chan, vms->fn);
04930 }
04931 if (!cmd)
04932 cmd = ast_play_and_wait(chan, "vm-messages");
04933 } else {
04934 if (!cmd)
04935 cmd = ast_play_and_wait(chan, "vm-messages");
04936 if (!cmd) {
04937 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04938 cmd = ast_play_and_wait(chan, vms->fn);
04939 }
04940 }
04941 }
04942 return cmd;
04943 }
04944
04945
04946 static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04947 {
04948 int cmd=0;
04949
04950 if (vms->lastmsg > -1) {
04951 cmd = play_message(chan, vmu, vms);
04952 } else {
04953 cmd = ast_play_and_wait(chan, "vm-youhave");
04954 if (!cmd)
04955 cmd = ast_play_and_wait(chan, "vm-no");
04956 if (!cmd) {
04957 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04958 cmd = ast_play_and_wait(chan, vms->fn);
04959 }
04960 if (!cmd)
04961 cmd = ast_play_and_wait(chan, "vm-messages");
04962 }
04963 return cmd;
04964 }
04965
04966
04967 static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04968 {
04969 int cmd=0;
04970
04971 if (vms->lastmsg > -1) {
04972 cmd = play_message(chan, vmu, vms);
04973 } else {
04974 cmd = ast_play_and_wait(chan, "vm-no");
04975 if (!cmd)
04976 cmd = ast_play_and_wait(chan, "vm-message");
04977 if (!cmd) {
04978 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04979 cmd = ast_play_and_wait(chan, vms->fn);
04980 }
04981 }
04982 return cmd;
04983 }
04984
04985
04986 static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
04987 {
04988 int cmd=0;
04989
04990 if (vms->lastmsg > -1) {
04991 cmd = play_message(chan, vmu, vms);
04992 } else {
04993 cmd = ast_play_and_wait(chan, "vm-youhaveno");
04994 if (!cmd)
04995 cmd = ast_play_and_wait(chan, "vm-messages");
04996 if (!cmd) {
04997 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
04998 cmd = ast_play_and_wait(chan, vms->fn);
04999 }
05000 }
05001 return cmd;
05002 }
05003
05004
05005 static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
05006 {
05007 int cmd=0;
05008
05009 if (vms->lastmsg > -1) {
05010 cmd = play_message(chan, vmu, vms);
05011 } else {
05012 cmd = ast_play_and_wait(chan, "vm-no");
05013 if (!cmd) {
05014 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
05015 cmd = ast_play_and_wait(chan, vms->fn);
05016 }
05017 if (!cmd)
05018 cmd = ast_play_and_wait(chan, "vm-messages");
05019 }
05020 return cmd;
05021 }
05022
05023 static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
05024 {
05025 if (!strcasecmp(chan->language, "es")) {
05026 return vm_browse_messages_es(chan, vms, vmu);
05027 } else if (!strcasecmp(chan->language, "it")) {
05028 return vm_browse_messages_it(chan, vms, vmu);
05029 } else if (!strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {
05030 return vm_browse_messages_pt(chan, vms, vmu);
05031 } else if (!strcasecmp(chan->language, "gr")){
05032 return vm_browse_messages_gr(chan, vms, vmu);
05033 } else {
05034 return vm_browse_messages_en(chan, vms, vmu);
05035 }
05036 }
05037
05038 static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size,
05039 struct ast_vm_user *res_vmu, const char *context, const char *prefix,
05040 int skipuser, int maxlogins, int silent)
05041 {
05042 int useadsi=0, valid=0, logretries=0;
05043 char password[AST_MAX_EXTENSION]="", *passptr;
05044 struct ast_vm_user vmus, *vmu = NULL;
05045
05046
05047 adsi_begin(chan, &useadsi);
05048 if (!skipuser && useadsi)
05049 adsi_login(chan);
05050 if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
05051 ast_log(LOG_WARNING, "Couldn't stream login file\n");
05052 return -1;
05053 }
05054
05055
05056
05057 while (!valid && (logretries < maxlogins)) {
05058
05059 if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
05060 ast_log(LOG_WARNING, "Couldn't read username\n");
05061 return -1;
05062 }
05063 if (ast_strlen_zero(mailbox)) {
05064 if (chan->cid.cid_num) {
05065 ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
05066 } else {
05067 if (option_verbose > 2)
05068 ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
05069 return -1;
05070 }
05071 }
05072 if (useadsi)
05073 adsi_password(chan);
05074
05075 if (!ast_strlen_zero(prefix)) {
05076 char fullusername[80] = "";
05077 ast_copy_string(fullusername, prefix, sizeof(fullusername));
05078 strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
05079 ast_copy_string(mailbox, fullusername, mailbox_size);
05080 }
05081
05082 vmu = find_user(&vmus, context, mailbox);
05083 if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
05084
05085 password[0] = '\0';
05086 } else {
05087 if (ast_streamfile(chan, "vm-password", chan->language)) {
05088 ast_log(LOG_WARNING, "Unable to stream password file\n");
05089 return -1;
05090 }
05091 if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
05092 ast_log(LOG_WARNING, "Unable to read password\n");
05093 return -1;
05094 }
05095 }
05096
05097 if (vmu) {
05098 passptr = vmu->password;
05099 if (passptr[0] == '-') passptr++;
05100 }
05101 if (vmu && !strcmp(passptr, password))
05102 valid++;
05103 else {
05104 if (option_verbose > 2)
05105 ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
05106 if (!ast_strlen_zero(prefix))
05107 mailbox[0] = '\0';
05108 }
05109 logretries++;
05110 if (!valid) {
05111 if (skipuser || logretries >= maxlogins) {
05112 if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
05113 ast_log(LOG_WARNING, "Unable to stream incorrect message\n");
05114 return -1;
05115 }
05116 } else {
05117 if (useadsi)
05118 adsi_login(chan);
05119 if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
05120 ast_log(LOG_WARNING, "Unable to stream incorrect mailbox message\n");
05121 return -1;
05122 }
05123 }
05124 if (ast_waitstream(chan, ""))
05125 return -1;
05126 }
05127 }
05128 if (!valid && (logretries >= maxlogins)) {
05129 ast_stopstream(chan);
05130 ast_play_and_wait(chan, "vm-goodbye");
05131 return -1;
05132 }
05133 if (vmu && !skipuser) {
05134 memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
05135 }
05136 return 0;
05137 }
05138
05139 static int vm_execmain(struct ast_channel *chan, void *data)
05140 {
05141
05142
05143
05144 int res=-1;
05145 int cmd=0;
05146 int valid = 0;
05147 struct localuser *u;
05148 char prefixstr[80] ="";
05149 char ext_context[256]="";
05150 int box;
05151 int useadsi = 0;
05152 int skipuser = 0;
05153 struct vm_state vms;
05154 struct ast_vm_user *vmu = NULL, vmus;
05155 char *context=NULL;
05156 int silentexit = 0;
05157 struct ast_flags flags = { 0 };
05158 signed char record_gain = 0;
05159
05160 LOCAL_USER_ADD(u);
05161
05162 memset(&vms, 0, sizeof(vms));
05163 vms.lastmsg = -1;
05164
05165 memset(&vmus, 0, sizeof(vmus));
05166
05167 if (chan->_state != AST_STATE_UP)
05168 ast_answer(chan);
05169
05170 if (!ast_strlen_zero(data)) {
05171 char *tmp;
05172 int argc;
05173 char *argv[2];
05174 char *opts[OPT_ARG_ARRAY_SIZE];
05175
05176 tmp = ast_strdupa(data);
05177 argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
05178 if (argc == 2) {
05179 if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
05180 LOCAL_USER_REMOVE(u);
05181 return -1;
05182 }
05183 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
05184 int gain;
05185
05186 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
05187 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
05188 LOCAL_USER_REMOVE(u);
05189 return -1;
05190 } else {
05191 record_gain = (signed char) gain;
05192 }
05193 }
05194 } else {
05195
05196 while (*argv[0]) {
05197 if (*argv[0] == 's') {
05198 ast_set_flag(&flags, OPT_SILENT);
05199 argv[0]++;
05200 } else if (*argv[0] == 'p') {
05201 ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
05202 argv[0]++;
05203 } else
05204 break;
05205 }
05206
05207 }
05208
05209 valid = ast_test_flag(&flags, OPT_SILENT);
05210
05211 if ((context = strchr(argv[0], '@')))
05212 *context++ = '\0';
05213
05214 if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
05215 ast_copy_string(prefixstr, argv[0], sizeof(prefixstr));
05216 else
05217 ast_copy_string(vms.username, argv[0], sizeof(vms.username));
05218
05219 if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
05220 skipuser++;
05221 else {
05222 if (!ast_strlen_zero(vms.username))
05223 ast_log(LOG_NOTICE, "Specified user '%s%s%s' not found (check voicemail.conf and/or realtime config). Falling back to authentication mode.\n", vms.username, context ? "@" : "", context ? context : "");
05224 valid = 0;
05225 }
05226 }
05227
05228 if (!valid)
05229 res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
05230
05231 if (!res) {
05232 valid = 1;
05233 if (!skipuser)
05234 vmu = &vmus;
05235 } else {
05236 res = 0;
05237 }
05238
05239
05240 adsi_begin(chan, &useadsi);
05241
05242 if (!valid)
05243 goto out;
05244
05245 vms.deleted = calloc(vmu->maxmsg, sizeof(int));
05246 vms.heard = calloc(vmu->maxmsg, sizeof(int));
05247
05248
05249 if (!ast_strlen_zero(vmu->language))
05250 ast_copy_string(chan->language, vmu->language, sizeof(chan->language));
05251 create_dirpath(vms.curdir, sizeof(vms.curdir), vmu->context, vms.username, "");
05252
05253 res = open_mailbox(&vms, vmu, 1);
05254 if (res == ERROR_LOCK_PATH)
05255 goto out;
05256 vms.oldmessages = vms.lastmsg + 1;
05257
05258 res = open_mailbox(&vms, vmu, 0);
05259 if (res == ERROR_LOCK_PATH)
05260 goto out;
05261 vms.newmessages = vms.lastmsg + 1;
05262
05263
05264 if (!vms.newmessages && vms.oldmessages) {
05265
05266 res = open_mailbox(&vms, vmu, 1);
05267 if (res == ERROR_LOCK_PATH)
05268 goto out;
05269 }
05270
05271 if (useadsi)
05272 adsi_status(chan, &vms);
05273 res = 0;
05274
05275
05276 if (!strcasecmp(vmu->mailbox, vmu->password) &&
05277 (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
05278 if (ast_play_and_wait(chan, "vm-newuser") == -1)
05279 ast_log(LOG_WARNING, "Couldn't stream new user file\n");
05280 cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
05281 if ((cmd == 't') || (cmd == '#')) {
05282
05283 res = 0;
05284 goto out;
05285 } else if (cmd < 0) {
05286
05287 res = -1;
05288 goto out;
05289 }
05290 }
05291
05292 cmd = vm_intro(chan, &vms);
05293
05294 vms.repeats = 0;
05295 vms.starting = 1;
05296 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
05297
05298 switch(cmd) {
05299 case '1':
05300 vms.curmsg = 0;
05301
05302 case '5':
05303 cmd = vm_browse_messages(chan, &vms, vmu);
05304 break;
05305 case '2':
05306 if (useadsi)
05307 adsi_folders(chan, 0, "Change to folder...");
05308 cmd = get_folder2(chan, "vm-changeto", 0);
05309 if (cmd == '#') {
05310 cmd = 0;
05311 } else if (cmd > 0) {
05312 cmd = cmd - '0';
05313 res = close_mailbox(&vms, vmu);
05314 if (res == ERROR_LOCK_PATH)
05315 goto out;
05316 res = open_mailbox(&vms, vmu, cmd);
05317 if (res == ERROR_LOCK_PATH)
05318 goto out;
05319 cmd = 0;
05320 }
05321 if (useadsi)
05322 adsi_status2(chan, &vms);
05323
05324 if (!cmd)
05325 cmd = vm_play_folder_name(chan, vms.vmbox);
05326
05327 vms.starting = 1;
05328 break;
05329 case '3':
05330 cmd = 0;
05331 vms.repeats = 0;
05332 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
05333 switch(cmd) {
05334 case '1':
05335 if (vms.lastmsg > -1 && !vms.starting) {
05336 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
05337 if (cmd == ERROR_LOCK_PATH) {
05338 res = cmd;
05339 goto out;
05340 }
05341 } else
05342 cmd = ast_play_and_wait(chan, "vm-sorry");
05343 cmd = 't';
05344 break;
05345 case '2':
05346 if (option_verbose > 2 && !vms.starting)
05347 ast_verbose( VERBOSE_PREFIX_3 "Callback Requested\n");
05348 if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
05349 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
05350 if (cmd == 9) {
05351 silentexit = 1;
05352 goto out;
05353 } else if (cmd == ERROR_LOCK_PATH) {
05354 res = cmd;
05355 goto out;
05356 }
05357 }
05358 else
05359 cmd = ast_play_and_wait(chan, "vm-sorry");
05360 cmd = 't';
05361 break;
05362 case '3':
05363 if (vms.lastmsg > -1 && !vms.starting) {
05364 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
05365 if (cmd == ERROR_LOCK_PATH) {
05366 res = cmd;
05367 goto out;
05368 }
05369 } else
05370 cmd = ast_play_and_wait(chan, "vm-sorry");
05371 cmd = 't';
05372 break;
05373 case '4':
05374 if (!ast_strlen_zero(vmu->dialout)) {
05375 cmd = dialout(chan, vmu, NULL, vmu->dialout);
05376 if (cmd == 9) {
05377 silentexit = 1;
05378 goto out;
05379 }
05380 }
05381 else
05382 cmd = ast_play_and_wait(chan, "vm-sorry");
05383 cmd = 't';
05384 break;
05385
05386 case '5':
05387 if (ast_test_flag(vmu, VM_SVMAIL)) {
05388 cmd = forward_message(chan, vmu->context, vms.curdir, vms.curmsg, vmu, vmfmts, 1, record_gain);
05389 if (cmd == ERROR_LOCK_PATH) {
05390 res = cmd;
05391 goto out;
05392 }
05393 } else
05394 cmd = ast_play_and_wait(chan,"vm-sorry");
05395 cmd='t';
05396 break;
05397
05398 case '*':
05399 cmd = 't';
05400 break;
05401
05402 default:
05403 cmd = 0;
05404 if (!vms.starting) {
05405 cmd = ast_play_and_wait(chan, "vm-toreply");
05406 }
05407 if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
05408 cmd = ast_play_and_wait(chan, "vm-tocallback");
05409 }
05410 if (!cmd && !vms.starting) {
05411 cmd = ast_play_and_wait(chan, "vm-tohearenv");
05412 }
05413 if (!ast_strlen_zero(vmu->dialout) && !cmd) {
05414 cmd = ast_play_and_wait(chan, "vm-tomakecall");
05415 }
05416 if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
05417 cmd=ast_play_and_wait(chan, "vm-leavemsg");
05418 if (!cmd)
05419 cmd = ast_play_and_wait(chan, "vm-starmain");
05420 if (!cmd)
05421 cmd = ast_waitfordigit(chan,6000);
05422 if (!cmd)
05423 vms.repeats++;
05424 if (vms.repeats > 3)
05425 cmd = 't';
05426 }
05427 }
05428 if (cmd == 't') {
05429 cmd = 0;
05430 vms.repeats = 0;
05431 }
05432 break;
05433 case '4':
05434 if (vms.curmsg) {
05435 vms.curmsg--;
05436 cmd = play_message(chan, vmu, &vms);
05437 } else {
05438 cmd = ast_play_and_wait(chan, "vm-nomore");
05439 }
05440 break;
05441 case '6':
05442 if (vms.curmsg < vms.lastmsg) {
05443 vms.curmsg++;
05444 cmd = play_message(chan, vmu, &vms);
05445 } else {
05446 cmd = ast_play_and_wait(chan, "vm-nomore");
05447 }
05448 break;
05449 case '7':
05450 vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
05451 if (useadsi)
05452 adsi_delete(chan, &vms);
05453 if (vms.deleted[vms.curmsg])
05454 cmd = ast_play_and_wait(chan, "vm-deleted");
05455 else
05456 cmd = ast_play_and_wait(chan, "vm-undeleted");
05457 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
05458 if (vms.curmsg < vms.lastmsg) {
05459 vms.curmsg++;
05460 cmd = play_message(chan, vmu, &vms);
05461 } else {
05462 cmd = ast_play_and_wait(chan, "vm-nomore");
05463 }
05464 }
05465 break;
05466
05467 case '8':
05468 if (vms.lastmsg > -1) {
05469 cmd = forward_message(chan, vmu->context, vms.curdir, vms.curmsg, vmu, vmfmts, 0, record_gain);
05470 if (cmd == ERROR_LOCK_PATH) {
05471 res = cmd;
05472 goto out;
05473 }
05474 } else
05475 cmd = ast_play_and_wait(chan, "vm-nomore");
05476 break;
05477 case '9':
05478 if (useadsi)
05479 adsi_folders(chan, 1, "Save to folder...");
05480 cmd = get_folder2(chan, "vm-savefolder", 1);
05481 box = 0;
05482 if (cmd == '#') {
05483 cmd = 0;
05484 break;
05485 } else if (cmd > 0) {
05486 box = cmd = cmd - '0';
05487 cmd = save_to_folder(vmu, vms.curdir, vms.curmsg, vmu->context, vms.username, cmd);
05488 if (cmd == ERROR_LOCK_PATH) {
05489 res = cmd;
05490 goto out;
05491 } else if (!cmd) {
05492 vms.deleted[vms.curmsg] = 1;
05493 } else {
05494 vms.deleted[vms.curmsg] = 0;
05495 vms.heard[vms.curmsg] = 0;
05496 }
05497 }
05498 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
05499 if (useadsi)
05500 adsi_message(chan, &vms);
05501 snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
05502 if (!cmd) {
05503 cmd = ast_play_and_wait(chan, "vm-message");
05504 if (!cmd)
05505 cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
05506 if (!cmd)
05507 cmd = ast_play_and_wait(chan, "vm-savedto");
05508 if (!cmd)
05509 cmd = vm_play_folder_name(chan, vms.fn);
05510 } else {
05511 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
05512 }
05513 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
05514 if (vms.curmsg < vms.lastmsg) {
05515 vms.curmsg++;
05516 cmd = play_message(chan, vmu, &vms);
05517 } else {
05518 cmd = ast_play_and_wait(chan, "vm-nomore");
05519 }
05520 }
05521 break;
05522 case '*':
05523 if (!vms.starting) {
05524 cmd = ast_play_and_wait(chan, "vm-onefor");
05525 if (!cmd)
05526 cmd = vm_play_folder_name(chan, vms.vmbox);
05527 if (!cmd)
05528 cmd = ast_play_and_wait(chan, "vm-opts");
05529 if (!cmd)
05530 cmd = vm_instructions(chan, &vms, 1);
05531 } else
05532 cmd = 0;
05533 break;
05534 case '0':
05535 cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
05536 if (useadsi)
05537 adsi_status(chan, &vms);
05538 break;
05539 default:
05540 cmd = vm_instructions(chan, &vms, 0);
05541 break;
05542 }
05543 }
05544 if ((cmd == 't') || (cmd == '#')) {
05545
05546 res = 0;
05547 } else {
05548
05549 res = -1;
05550 }
05551
05552 out:
05553 if (res > -1) {
05554 ast_stopstream(chan);
05555 adsi_goodbye(chan);
05556 if (valid) {
05557 if (silentexit)
05558 res = ast_play_and_wait(chan, "vm-dialout");
05559 else
05560 res = ast_play_and_wait(chan, "vm-goodbye");
05561 if (res > 0)
05562 res = 0;
05563 }
05564 if (useadsi)
05565 adsi_unload_session(chan);
05566 }
05567 if (vmu)
05568 close_mailbox(&vms, vmu);
05569 if (valid) {
05570 snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
05571 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
05572 run_externnotify(vmu->context, vmu->mailbox);
05573 }
05574 if (vmu)
05575 free_user(vmu);
05576 if (vms.deleted)
05577 free(vms.deleted);
05578 if (vms.heard)
05579 free(vms.heard);
05580 LOCAL_USER_REMOVE(u);
05581
05582 return res;
05583 }
05584
05585 static int vm_exec(struct ast_channel *chan, void *data)
05586 {
05587 int res = 0;
05588 struct localuser *u;
05589 char *tmp;
05590 struct leave_vm_options leave_options;
05591 int argc;
05592 char *argv[2];
05593 struct ast_flags flags = { 0 };
05594 char *opts[OPT_ARG_ARRAY_SIZE];
05595
05596 LOCAL_USER_ADD(u);
05597
05598 memset(&leave_options, 0, sizeof(leave_options));
05599
05600 if (chan->_state != AST_STATE_UP)
05601 ast_answer(chan);
05602
05603 if (!ast_strlen_zero(data)) {
05604 tmp = ast_strdupa((char *)data);
05605 if (!tmp) {
05606 ast_log(LOG_ERROR, "Out of memory\n");
05607 LOCAL_USER_REMOVE(u);
05608 return -1;
05609 }
05610 argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
05611 if (argc == 2) {
05612 if (ast_app_parse_options(vm_app_options, &flags, opts, argv[1])) {
05613 LOCAL_USER_REMOVE(u);
05614 return -1;
05615 }
05616 ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_PRIORITY_JUMP);
05617 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
05618 int gain;
05619
05620 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
05621 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
05622 LOCAL_USER_REMOVE(u);
05623 return -1;
05624 } else {
05625 leave_options.record_gain = (signed char) gain;
05626 }
05627 }
05628 } else {
05629
05630 while (*argv[0]) {
05631 if (*argv[0] == 's') {
05632 ast_set_flag(&leave_options, OPT_SILENT);
05633 argv[0]++;
05634 } else if (*argv[0] == 'b') {
05635 ast_set_flag(&leave_options, OPT_BUSY_GREETING);
05636 argv[0]++;
05637 } else if (*argv[0] == 'u') {
05638 ast_set_flag(&leave_options, OPT_UNAVAIL_GREETING);
05639 argv[0]++;
05640 } else if (*argv[0] == 'j') {
05641 ast_set_flag(&leave_options, OPT_PRIORITY_JUMP);
05642 argv[0]++;
05643 } else
05644 break;
05645 }
05646 }
05647 } else {
05648 char tmp[256];
05649 res = ast_app_getdata(chan, "vm-whichbox", tmp, sizeof(tmp) - 1, 0);
05650 if (res < 0) {
05651 LOCAL_USER_REMOVE(u);
05652 return res;
05653 }
05654 if (ast_strlen_zero(tmp)) {
05655 LOCAL_USER_REMOVE(u);
05656 return 0;
05657 }
05658 argv[0] = ast_strdupa(tmp);
05659 }
05660
05661 res = leave_voicemail(chan, argv[0], &leave_options);
05662
05663 if (res == ERROR_LOCK_PATH) {
05664 ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
05665
05666 if (ast_test_flag(&leave_options, OPT_PRIORITY_JUMP) || option_priority_jumping)
05667 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
05668 ast_log(LOG_WARNING, "Extension %s, priority %d doesn't exist.\n", chan->exten, chan->priority + 101);
05669 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
05670 res = 0;
05671 }
05672
05673 LOCAL_USER_REMOVE(u);
05674
05675 return res;
05676 }
05677
05678 static int append_mailbox(char *context, char *mbox, char *data)
05679 {
05680
05681 char tmp[256] = "";
05682 char *stringp;
05683 char *s;
05684 struct ast_vm_user *vmu;
05685
05686 ast_copy_string(tmp, data, sizeof(tmp));
05687 vmu = malloc(sizeof(struct ast_vm_user));
05688 if (vmu) {
05689 memset(vmu, 0, sizeof(struct ast_vm_user));
05690 ast_copy_string(vmu->context, context, sizeof(vmu->context));
05691 ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
05692
05693 populate_defaults(vmu);
05694
05695 stringp = tmp;
05696 if ((s = strsep(&stringp, ",")))
05697 ast_copy_string(vmu->password, s, sizeof(vmu->password));
05698 if (stringp && (s = strsep(&stringp, ",")))
05699 ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
05700 if (stringp && (s = strsep(&stringp, ",")))
05701 ast_copy_string(vmu->email, s, sizeof(vmu->email));
05702 if (stringp && (s = strsep(&stringp, ",")))
05703 ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
05704 if (stringp && (s = strsep(&stringp, ",")))
05705 apply_options(vmu, s);
05706
05707 vmu->next = NULL;
05708 if (usersl)
05709 usersl->next = vmu;
05710 else
05711 users = vmu;
05712 usersl = vmu;
05713 }
05714 return 0;
05715 }
05716
05717 static int vm_box_exists(struct ast_channel *chan, void *data)
05718 {
05719 struct localuser *u;
05720 struct ast_vm_user svm;
05721 char *context, *box;
05722 int priority_jump = 0;
05723 AST_DECLARE_APP_ARGS(args,
05724 AST_APP_ARG(mbox);
05725 AST_APP_ARG(options);
05726 );
05727
05728 if (ast_strlen_zero(data)) {
05729 ast_log(LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
05730 return -1;
05731 }
05732
05733 LOCAL_USER_ADD(u);
05734
05735 box = ast_strdupa(data);
05736 if (!box) {
05737 ast_log(LOG_ERROR, "Out of memory\n");
05738 LOCAL_USER_REMOVE(u);
05739 return -1;
05740 }
05741
05742 AST_STANDARD_APP_ARGS(args, box);
05743
05744 if (args.options) {
05745 if (strchr(args.options, 'j'))
05746 priority_jump = 1;
05747 }
05748
05749 if ((context = strchr(args.mbox, '@'))) {
05750 *context = '\0';
05751 context++;
05752 }
05753
05754 if (find_user(&svm, context, args.mbox)) {
05755 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
05756 if (priority_jump || option_priority_jumping)
05757 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
05758 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);
05759 } else
05760 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
05761 LOCAL_USER_REMOVE(u);
05762 return 0;
05763 }
05764
05765 static int vmauthenticate(struct ast_channel *chan, void *data)
05766 {
05767 struct localuser *u;
05768 char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
05769 struct ast_vm_user vmus;
05770 char *options = NULL;
05771 int silent = 0, skipuser = 0;
05772 int res = -1;
05773
05774 LOCAL_USER_ADD(u);
05775
05776 if (s) {
05777 s = ast_strdupa(s);
05778 if (!s) {
05779 ast_log(LOG_ERROR, "Out of memory\n");
05780 return -1;
05781 }
05782 user = strsep(&s, "|");
05783 options = strsep(&s, "|");
05784 if (user) {
05785 s = user;
05786 user = strsep(&s, "@");
05787 context = strsep(&s, "");
05788 if (!ast_strlen_zero(user))
05789 skipuser++;
05790 ast_copy_string(mailbox, user, sizeof(mailbox));
05791 }
05792 }
05793
05794 if (options) {
05795 silent = (strchr(options, 's')) != NULL;
05796 }
05797
05798 if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
05799 pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
05800 pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
05801 ast_play_and_wait(chan, "auth-thankyou");
05802 res = 0;
05803 }
05804
05805 LOCAL_USER_REMOVE(u);
05806 return res;
05807 }
05808
05809 static char show_voicemail_users_help[] =
05810 "Usage: show voicemail users [for <context>]\n"
05811 " Lists all mailboxes currently set up\n";
05812
05813 static char show_voicemail_zones_help[] =
05814 "Usage: show voicemail zones\n"
05815 " Lists zone message formats\n";
05816
05817 static int handle_show_voicemail_users(int fd, int argc, char *argv[])
05818 {
05819 struct ast_vm_user *vmu = users;
05820 char *output_format = "%-10s %-5s %-25s %-10s %6s\n";
05821
05822 if ((argc < 3) || (argc > 5) || (argc == 4)) return RESULT_SHOWUSAGE;
05823 else if ((argc == 5) && strcmp(argv[3],"for")) return RESULT_SHOWUSAGE;
05824
05825 if (vmu) {
05826 if (argc == 3)
05827 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
05828 else {
05829 int count = 0;
05830 while (vmu) {
05831 if (!strcmp(argv[4],vmu->context))
05832 count++;
05833 vmu = vmu->next;
05834 }
05835 if (count) {
05836 vmu = users;
05837 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
05838 } else {
05839 ast_cli(fd, "No such voicemail context \"%s\"\n", argv[4]);
05840 return RESULT_FAILURE;
05841 }
05842 }
05843 while (vmu) {
05844 char dirname[256];
05845 DIR *vmdir;
05846 struct dirent *vment;
05847 int vmcount = 0;
05848 char count[12];
05849
05850 if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) {
05851 make_dir(dirname, 255, vmu->context, vmu->mailbox, "INBOX");
05852 if ((vmdir = opendir(dirname))) {
05853
05854 while ((vment = readdir(vmdir)))
05855 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7,".txt",4))
05856 vmcount++;
05857 closedir(vmdir);
05858 }
05859 snprintf(count,sizeof(count),"%d",vmcount);
05860 ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
05861 }
05862 vmu = vmu->next;
05863 }
05864 } else {
05865 ast_cli(fd, "There are no voicemail users currently defined\n");
05866 return RESULT_FAILURE;
05867 }
05868 return RESULT_SUCCESS;
05869 }
05870
05871 static int handle_show_voicemail_zones(int fd, int argc, char *argv[])
05872 {
05873 struct vm_zone *zone = zones;
05874 char *output_format = "%-15s %-20s %-45s\n";
05875
05876 if (argc != 3) return RESULT_SHOWUSAGE;
05877
05878 if (zone) {
05879 ast_cli(fd, output_format, "Zone", "Timezone", "Message Format");
05880 while (zone) {
05881 ast_cli(fd, output_format, zone->name, zone->timezone, zone->msg_format);
05882 zone = zone->next;
05883 }
05884 } else {
05885 ast_cli(fd, "There are no voicemail zones currently defined\n");
05886 return RESULT_FAILURE;
05887 }
05888 return RESULT_SUCCESS;
05889 }
05890
05891 static char *complete_show_voicemail_users(char *line, char *word, int pos, int state)
05892 {
05893 int which = 0;
05894 struct ast_vm_user *vmu = users;
05895 char *context = "";
05896
05897
05898 if (pos > 4)
05899 return NULL;
05900 if (pos == 3) {
05901 if (state == 0)
05902 return strdup("for");
05903 else
05904 return NULL;
05905 }
05906 while (vmu) {
05907 if (!strncasecmp(word, vmu->context, strlen(word))) {
05908 if (context && strcmp(context, vmu->context)) {
05909 if (++which > state) {
05910 return strdup(vmu->context);
05911 }
05912 context = vmu->context;
05913 }
05914 }
05915 vmu = vmu->next;
05916 }
05917 return NULL;
05918 }
05919
05920 static struct ast_cli_entry show_voicemail_users_cli =
05921 { { "show", "voicemail", "users", NULL },
05922 handle_show_voicemail_users, "List defined voicemail boxes",
05923 show_voicemail_users_help, complete_show_voicemail_users };
05924
05925 static struct ast_cli_entry show_voicemail_zones_cli =
05926 { { "show", "voicemail", "zones", NULL },
05927 handle_show_voicemail_zones, "List zone message formats",
05928 show_voicemail_zones_help, NULL };
05929
05930 static int load_config(void)
05931 {
05932 struct ast_vm_user *cur, *l;
05933 struct vm_zone *zcur, *zl;
05934 struct ast_config *cfg;
05935 char *cat;
05936 struct ast_variable *var;
05937 char *notifystr = NULL;
05938 char *astattach;
05939 char *astsearch;
05940 char *astsaycid;
05941 char *send_voicemail;
05942 char *astcallop;
05943 char *astreview;
05944 char *astskipcmd;
05945 char *asthearenv;
05946 char *astsaydurationinfo;
05947 char *astsaydurationminfo;
05948 char *silencestr;
05949 char *maxmsgstr;
05950 char *astdirfwd;
05951 char *thresholdstr;
05952 char *fmt;
05953 char *astemail;
05954 char *astmailcmd = SENDMAIL;
05955 char *s,*q,*stringp;
05956 char *dialoutcxt = NULL;
05957 char *callbackcxt = NULL;
05958 char *exitcxt = NULL;
05959 char *extpc;
05960 char *emaildateformatstr;
05961 int x;
05962 int tmpadsi[4];
05963
05964 cfg = ast_config_load(VOICEMAIL_CONFIG);
05965 ast_mutex_lock(&vmlock);
05966 cur = users;
05967 while (cur) {
05968 l = cur;
05969 cur = cur->next;
05970 ast_set_flag(l, VM_ALLOCED);
05971 free_user(l);
05972 }
05973 zcur = zones;
05974 while (zcur) {
05975 zl = zcur;
05976 zcur = zcur->next;
05977 free_zone(zl);
05978 }
05979 zones = NULL;
05980 zonesl = NULL;
05981 users = NULL;
05982 usersl = NULL;
05983 memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
05984
05985 if (cfg) {
05986
05987
05988
05989 if (!(astattach = ast_variable_retrieve(cfg, "general", "attach")))
05990 astattach = "yes";
05991 ast_set2_flag((&globalflags), ast_true(astattach), VM_ATTACH);
05992
05993 if (!(astsearch = ast_variable_retrieve(cfg, "general", "searchcontexts")))
05994 astsearch = "no";
05995 ast_set2_flag((&globalflags), ast_true(astsearch), VM_SEARCH);
05996
05997 #ifdef USE_ODBC_STORAGE
05998 strcpy(odbc_database, "asterisk");
05999 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
06000 ast_copy_string(odbc_database, thresholdstr, sizeof(odbc_database));
06001 }
06002 strcpy(odbc_table, "voicemessages");
06003 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbctable"))) {
06004 ast_copy_string(odbc_table, thresholdstr, sizeof(odbc_table));
06005 }
06006 #endif
06007
06008 strcpy(mailcmd, SENDMAIL);
06009 if ((astmailcmd = ast_variable_retrieve(cfg, "general", "mailcmd")))
06010 ast_copy_string(mailcmd, astmailcmd, sizeof(mailcmd));
06011
06012 maxsilence = 0;
06013 if ((silencestr = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
06014 maxsilence = atoi(silencestr);
06015 if (maxsilence > 0)
06016 maxsilence *= 1000;
06017 }
06018
06019 if (!(maxmsgstr = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
06020 maxmsg = MAXMSG;
06021 } else {
06022 maxmsg = atoi(maxmsgstr);
06023 if (maxmsg <= 0) {
06024 ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", maxmsgstr, MAXMSG);
06025 maxmsg = MAXMSG;
06026 } else if (maxmsg > MAXMSGLIMIT) {
06027 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, maxmsgstr);
06028 maxmsg = MAXMSGLIMIT;
06029 }
06030 }
06031
06032
06033 if ((emaildateformatstr = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
06034 ast_copy_string(emaildateformat, emaildateformatstr, sizeof(emaildateformat));
06035 }
06036
06037
06038 if ((extpc = ast_variable_retrieve(cfg, "general", "externpass"))) {
06039 ast_copy_string(ext_pass_cmd,extpc,sizeof(ext_pass_cmd));
06040 }
06041
06042
06043
06044 if ((notifystr = ast_variable_retrieve(cfg, "general", "externnotify"))) {
06045 ast_copy_string(externnotify, notifystr, sizeof(externnotify));
06046 ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify);
06047 } else {
06048 externnotify[0] = '\0';
06049 }
06050
06051
06052 silencethreshold = 256;
06053 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
06054 silencethreshold = atoi(thresholdstr);
06055
06056 if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
06057 astemail = ASTERISK_USERNAME;
06058 ast_copy_string(serveremail, astemail, sizeof(serveremail));
06059
06060 vmmaxmessage = 0;
06061 if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
06062 if (sscanf(s, "%d", &x) == 1) {
06063 vmmaxmessage = x;
06064 } else {
06065 ast_log(LOG_WARNING, "Invalid max message time length\n");
06066 }
06067 }
06068
06069 vmminmessage = 0;
06070 if ((s = ast_variable_retrieve(cfg, "general", "minmessage"))) {
06071 if (sscanf(s, "%d", &x) == 1) {
06072 vmminmessage = x;
06073 if (maxsilence <= vmminmessage)
06074 ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
06075 } else {
06076 ast_log(LOG_WARNING, "Invalid min message time length\n");
06077 }
06078 }
06079 fmt = ast_variable_retrieve(cfg, "general", "format");
06080 if (!fmt)
06081 fmt = "wav";
06082 ast_copy_string(vmfmts, fmt, sizeof(vmfmts));
06083
06084 skipms = 3000;
06085 if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
06086 if (sscanf(s, "%d", &x) == 1) {
06087 maxgreet = x;
06088 } else {
06089 ast_log(LOG_WARNING, "Invalid max message greeting length\n");
06090 }
06091 }
06092
06093 if ((s = ast_variable_retrieve(cfg, "general", "skipms"))) {
06094 if (sscanf(s, "%d", &x) == 1) {
06095 skipms = x;
06096 } else {
06097 ast_log(LOG_WARNING, "Invalid skipms value\n");
06098 }
06099 }
06100
06101 maxlogins = 3;
06102 if ((s = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
06103 if (sscanf(s, "%d", &x) == 1) {
06104 maxlogins = x;
06105 } else {
06106 ast_log(LOG_WARNING, "Invalid max failed login attempts\n");
06107 }
06108 }
06109
06110
06111 if (!(astattach = ast_variable_retrieve(cfg, "general", "forcename")))
06112 astattach = "no";
06113 ast_set2_flag((&globalflags), ast_true(astattach), VM_FORCENAME);
06114
06115
06116 if (!(astattach = ast_variable_retrieve(cfg, "general", "forcegreetings")))
06117 astattach = "no";
06118 ast_set2_flag((&globalflags), ast_true(astattach), VM_FORCEGREET);
06119
06120 if ((s = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))){
06121 ast_log(LOG_DEBUG,"VM_CID Internal context string: %s\n",s);
06122 stringp = ast_strdupa(s);
06123 for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
06124 if (!ast_strlen_zero(stringp)) {
06125 q = strsep(&stringp,",");
06126 while ((*q == ' ')||(*q == '\t'))
06127 q++;
06128 ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
06129 ast_log(LOG_DEBUG,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
06130 } else {
06131 cidinternalcontexts[x][0] = '\0';
06132 }
06133 }
06134 }
06135 if (!(astreview = ast_variable_retrieve(cfg, "general", "review"))){
06136 ast_log(LOG_DEBUG,"VM Review Option disabled globally\n");
06137 astreview = "no";
06138 }
06139 ast_set2_flag((&globalflags), ast_true(astreview), VM_REVIEW);
06140
06141 if (!(astcallop = ast_variable_retrieve(cfg, "general", "operator"))){
06142 ast_log(LOG_DEBUG,"VM Operator break disabled globally\n");
06143 astcallop = "no";
06144 }
06145 ast_set2_flag((&globalflags), ast_true(astcallop), VM_OPERATOR);
06146
06147 if (!(astsaycid = ast_variable_retrieve(cfg, "general", "saycid"))) {
06148 ast_log(LOG_DEBUG,"VM CID Info before msg disabled globally\n");
06149 astsaycid = "no";
06150 }
06151 ast_set2_flag((&globalflags), ast_true(astsaycid), VM_SAYCID);
06152
06153 if (!(send_voicemail = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
06154 ast_log(LOG_DEBUG,"Send Voicemail msg disabled globally\n");
06155 send_voicemail = "no";
06156 }
06157 ast_set2_flag((&globalflags), ast_true(send_voicemail), VM_SVMAIL);
06158
06159 if (!(asthearenv = ast_variable_retrieve(cfg, "general", "envelope"))) {
06160 ast_log(LOG_DEBUG,"ENVELOPE before msg enabled globally\n");
06161 asthearenv = "yes";
06162 }
06163 ast_set2_flag((&globalflags), ast_true(asthearenv), VM_ENVELOPE);
06164
06165 if (!(astsaydurationinfo = ast_variable_retrieve(cfg, "general", "sayduration"))) {
06166 ast_log(LOG_DEBUG,"Duration info before msg enabled globally\n");
06167 astsaydurationinfo = "yes";
06168 }
06169 ast_set2_flag((&globalflags), ast_true(astsaydurationinfo), VM_SAYDURATION);
06170
06171 saydurationminfo = 2;
06172 if ((astsaydurationminfo = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
06173 if (sscanf(astsaydurationminfo, "%d", &x) == 1) {
06174 saydurationminfo = x;
06175 } else {
06176 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
06177 }
06178 }
06179
06180 if (!(astskipcmd = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
06181 ast_log(LOG_DEBUG,"We are not going to skip to the next msg after save/delete\n");
06182 astskipcmd = "no";
06183 }
06184 ast_set2_flag((&globalflags), ast_true(astskipcmd), VM_SKIPAFTERCMD);
06185
06186 if ((dialoutcxt = ast_variable_retrieve(cfg, "general", "dialout"))) {
06187 ast_copy_string(dialcontext, dialoutcxt, sizeof(dialcontext));
06188 ast_log(LOG_DEBUG, "found dialout context: %s\n", dialcontext);
06189 } else {
06190 dialcontext[0] = '\0';
06191 }
06192
06193 if ((callbackcxt = ast_variable_retrieve(cfg, "general", "callback"))) {
06194 ast_copy_string(callcontext, callbackcxt, sizeof(callcontext));
06195 ast_log(LOG_DEBUG, "found callback context: %s\n", callcontext);
06196 } else {
06197 callcontext[0] = '\0';
06198 }
06199
06200 if ((exitcxt = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
06201 ast_copy_string(exitcontext, exitcxt, sizeof(exitcontext));
06202 ast_log(LOG_DEBUG, "found operator context: %s\n", exitcontext);
06203 } else {
06204 exitcontext[0] = '\0';
06205 }
06206
06207 if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory")))
06208 astdirfwd = "no";
06209 ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD);
06210 cat = ast_category_browse(cfg, NULL);
06211 while (cat) {
06212 if (strcasecmp(cat, "general")) {
06213 var = ast_variable_browse(cfg, cat);
06214 if (strcasecmp(cat, "zonemessages")) {
06215
06216 while (var) {
06217 append_mailbox(cat, var->name, var->value);
06218 var = var->next;
06219 }
06220 } else {
06221
06222 while (var) {
06223 struct vm_zone *z;
06224 z = malloc(sizeof(struct vm_zone));
06225 if (z != NULL) {
06226 char *msg_format, *timezone;
06227 msg_format = ast_strdupa(var->value);
06228 if (msg_format != NULL) {
06229 timezone = strsep(&msg_format, "|");
06230 if (msg_format) {
06231 ast_copy_string(z->name, var->name, sizeof(z->name));
06232 ast_copy_string(z->timezone, timezone, sizeof(z->timezone));
06233 ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
06234 z->next = NULL;
06235 if (zones) {
06236 zonesl->next = z;
06237 zonesl = z;
06238 } else {
06239 zones = z;
06240 zonesl = z;
06241 }
06242 } else {
06243 ast_log(LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
06244 free(z);
06245 }
06246 } else {
06247 ast_log(LOG_WARNING, "Out of memory while reading voicemail config\n");
06248 free(z);
06249 ast_mutex_unlock(&vmlock);
06250 ast_config_destroy(cfg);
06251 return -1;
06252 }
06253 } else {
06254 ast_log(LOG_WARNING, "Out of memory while reading voicemail config\n");
06255 ast_mutex_unlock(&vmlock);
06256 ast_config_destroy(cfg);
06257 return -1;
06258 }
06259 var = var->next;
06260 }
06261 }
06262 }
06263 cat = ast_category_browse(cfg, cat);
06264 }
06265 memset(fromstring,0,sizeof(fromstring));
06266 memset(pagerfromstring,0,sizeof(pagerfromstring));
06267 memset(emailtitle,0,sizeof(emailtitle));
06268 strcpy(charset, "ISO-8859-1");
06269 if (emailbody) {
06270 free(emailbody);
06271 emailbody = NULL;
06272 }
06273 if (emailsubject) {
06274 free(emailsubject);
06275 emailsubject = NULL;
06276 }
06277 if (pagerbody) {
06278 free(pagerbody);
06279 pagerbody = NULL;
06280 }
06281 if (pagersubject) {
06282 free(pagersubject);
06283 pagersubject = NULL;
06284 }
06285 if ((s=ast_variable_retrieve(cfg, "general", "pbxskip")))
06286 ast_set2_flag((&globalflags), ast_true(s), VM_PBXSKIP);
06287 if ((s=ast_variable_retrieve(cfg, "general", "fromstring")))
06288 ast_copy_string(fromstring,s,sizeof(fromstring));
06289 if ((s=ast_variable_retrieve(cfg, "general", "pagerfromstring")))
06290 ast_copy_string(pagerfromstring,s,sizeof(pagerfromstring));
06291 if ((s=ast_variable_retrieve(cfg, "general", "charset")))
06292 ast_copy_string(charset,s,sizeof(charset));
06293 if ((s=ast_variable_retrieve(cfg, "general", "adsifdn"))) {
06294 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
06295 for (x=0; x<4; x++) {
06296 memcpy(&adsifdn[x], &tmpadsi[x], 1);
06297 }
06298 }
06299 if ((s=ast_variable_retrieve(cfg, "general", "adsisec"))) {
06300 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
06301 for (x=0; x<4; x++) {
06302 memcpy(&adsisec[x], &tmpadsi[x], 1);
06303 }
06304 }
06305 if ((s=ast_variable_retrieve(cfg, "general", "adsiver")))
06306 if (atoi(s)) {
06307 adsiver = atoi(s);
06308 }
06309 if ((s=ast_variable_retrieve(cfg, "general", "emailtitle"))) {
06310 ast_log(LOG_NOTICE, "Keyword 'emailtitle' is DEPRECATED, please use 'emailsubject' instead.\n");
06311 ast_copy_string(emailtitle,s,sizeof(emailtitle));
06312 }
06313 if ((s=ast_variable_retrieve(cfg, "general", "emailsubject")))
06314 emailsubject = strdup(s);
06315 if ((s=ast_variable_retrieve(cfg, "general", "emailbody"))) {
06316 char *tmpread, *tmpwrite;
06317 emailbody = strdup(s);
06318
06319
06320 tmpread = tmpwrite = emailbody;
06321 while ((tmpwrite = strchr(tmpread,'\\'))) {
06322 int len = strlen("\n");
06323 switch (tmpwrite[1]) {
06324 case 'n':
06325 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06326 strncpy(tmpwrite,"\n",len);
06327 break;
06328 case 't':
06329 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06330 strncpy(tmpwrite,"\t",len);
06331 break;
06332 default:
06333 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n",tmpwrite[1]);
06334 }
06335 tmpread = tmpwrite+len;
06336 }
06337 }
06338 if ((s=ast_variable_retrieve(cfg, "general", "pagersubject")))
06339 pagersubject = strdup(s);
06340 if ((s=ast_variable_retrieve(cfg, "general", "pagerbody"))) {
06341 char *tmpread, *tmpwrite;
06342 pagerbody = strdup(s);
06343
06344
06345 tmpread = tmpwrite = pagerbody;
06346 while ((tmpwrite = strchr(tmpread,'\\'))) {
06347 int len = strlen("\n");
06348 switch (tmpwrite[1]) {
06349 case 'n':
06350 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06351 strncpy(tmpwrite,"\n",len);
06352 break;
06353 case 't':
06354 strncpy(tmpwrite+len,tmpwrite+2,strlen(tmpwrite+2)+1);
06355 strncpy(tmpwrite,"\t",len);
06356 break;
06357 default:
06358 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n",tmpwrite[1]);
06359 }
06360 tmpread = tmpwrite+len;
06361 }
06362 }
06363 ast_mutex_unlock(&vmlock);
06364 ast_config_destroy(cfg);
06365 return 0;
06366 } else {
06367 ast_mutex_unlock(&vmlock);
06368 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
06369 return 0;
06370 }
06371 }
06372
06373 int reload(void)
06374 {
06375 return(load_config());
06376 }
06377
06378 int unload_module(void)
06379 {
06380 int res;
06381
06382 res = ast_unregister_application(app);
06383 res |= ast_unregister_application(app2);
06384 res |= ast_unregister_application(app3);
06385 res |= ast_unregister_application(app4);
06386 res |= ast_cli_unregister(&show_voicemail_users_cli);
06387 res |= ast_cli_unregister(&show_voicemail_zones_cli);
06388 ast_uninstall_vm_functions();
06389
06390 STANDARD_HANGUP_LOCALUSERS;
06391
06392 return res;
06393 }
06394
06395 int load_module(void)
06396 {
06397 int res;
06398 res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
06399 res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
06400 res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
06401 res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
06402 if (res)
06403 return(res);
06404
06405 if ((res=load_config())) {
06406 return(res);
06407 }
06408
06409 ast_cli_register(&show_voicemail_users_cli);
06410 ast_cli_register(&show_voicemail_zones_cli);
06411
06412
06413 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
06414
06415 ast_install_vm_functions(has_voicemail, messagecount);
06416
06417 #if defined(USE_ODBC_STORAGE) && !defined(EXTENDED_ODBC_STORAGE)
06418 ast_log(LOG_WARNING, "The current ODBC storage table format will be changed soon."
06419 "Please update your tables as per the README and edit the apps/Makefile "
06420 "and uncomment the line containing EXTENDED_ODBC_STORAGE to enable the "
06421 "new table format.\n");
06422 #endif
06423
06424 return res;
06425 }
06426
06427 char *description(void)
06428 {
06429 return tdesc;
06430 }
06431
06432 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
06433 {
06434 int cmd = 0;
06435 char destination[80] = "";
06436 int retries = 0;
06437
06438 if (!num) {
06439 if (option_verbose > 2)
06440 ast_verbose( VERBOSE_PREFIX_3 "Destination number will be entered manually\n");
06441 while (retries < 3 && cmd != 't') {
06442 destination[1] = '\0';
06443 destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
06444 if (!cmd)
06445 destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
06446 if (!cmd)
06447 destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
06448 if (!cmd) {
06449 cmd = ast_waitfordigit(chan, 6000);
06450 if (cmd)
06451 destination[0] = cmd;
06452 }
06453 if (!cmd) {
06454 retries++;
06455 } else {
06456
06457 if (cmd < 0)
06458 return 0;
06459 if (cmd == '*') {
06460 if (option_verbose > 2)
06461 ast_verbose( VERBOSE_PREFIX_3 "User hit '*' to cancel outgoing call\n");
06462 return 0;
06463 }
06464 if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0)
06465 retries++;
06466 else
06467 cmd = 't';
06468 }
06469 }
06470 if (retries >= 3) {
06471 return 0;
06472 }
06473
06474 } else {
06475 if (option_verbose > 2)
06476 ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
06477 ast_copy_string(destination, num, sizeof(destination));
06478 }
06479
06480 if (!ast_strlen_zero(destination)) {
06481 if (destination[strlen(destination) -1 ] == '*')
06482 return 0;
06483 if (option_verbose > 2)
06484 ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
06485 ast_copy_string(chan->exten, destination, sizeof(chan->exten));
06486 ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
06487 chan->priority = 0;
06488 return 9;
06489 }
06490 return 0;
06491 }
06492
06493 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg,
06494 int option, signed char record_gain)
06495 {
06496 int res = 0;
06497 char filename[256],*origtime, *cid, *context, *name, *num;
06498 struct ast_config *msg_cfg;
06499 int retries = 0;
06500
06501 vms->starting = 0;
06502 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
06503
06504
06505
06506 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
06507 snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
06508 RETRIEVE(vms->curdir, vms->curmsg);
06509 msg_cfg = ast_config_load(filename);
06510 DISPOSE(vms->curdir, vms->curmsg);
06511 if (!msg_cfg) {
06512 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
06513 return 0;
06514 }
06515
06516 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
06517 ast_config_destroy(msg_cfg);
06518 return 0;
06519 }
06520
06521 cid = ast_variable_retrieve(msg_cfg, "message", "callerid");
06522
06523 context = ast_variable_retrieve(msg_cfg, "message", "context");
06524 if (!strncasecmp("macro",context,5))
06525 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
06526
06527 ast_config_destroy(msg_cfg);
06528
06529 if (option == 3) {
06530
06531 if (!res)
06532 res = play_message_datetime(chan, vmu, origtime, filename);
06533 if (!res)
06534 res = play_message_callerid(chan, vms, cid, context, 0);
06535
06536 res = 't';
06537
06538 } else if (option == 2) {
06539
06540 if (!ast_strlen_zero(cid)) {
06541 ast_callerid_parse(cid, &name, &num);
06542 while ((res > -1) && (res != 't')) {
06543 switch(res) {
06544 case '1':
06545 if (num) {
06546
06547 res = dialout(chan, vmu, num, vmu->callback);
06548 if (res)
06549 return 9;
06550 } else {
06551 res = '2';
06552 }
06553 break;
06554
06555 case '2':
06556
06557 if (!ast_strlen_zero(vmu->dialout)) {
06558 res = dialout(chan, vmu, NULL, vmu->dialout);
06559 if (res)
06560 return 9;
06561 } else {
06562 if (option_verbose > 2)
06563 ast_verbose( VERBOSE_PREFIX_3 "Caller can not specify callback number - no dialout context available\n");
06564 res = ast_play_and_wait(chan, "vm-sorry");
06565 }
06566 return res;
06567 case '*':
06568 res = 't';
06569 break;
06570 case '3':
06571 case '4':
06572 case '5':
06573 case '6':
06574 case '7':
06575 case '8':
06576 case '9':
06577 case '0':
06578
06579 res = ast_play_and_wait(chan, "vm-sorry");
06580 retries++;
06581 break;
06582 default:
06583 if (num) {
06584 if (option_verbose > 2)
06585 ast_verbose( VERBOSE_PREFIX_3 "Confirm CID number '%s' is number to use for callback\n", num);
06586 res = ast_play_and_wait(chan, "vm-num-i-have");
06587 if (!res)
06588 res = play_message_callerid(chan, vms, num, vmu->context, 1);
06589 if (!res)
06590 res = ast_play_and_wait(chan, "vm-tocallnum");
06591
06592 if (!ast_strlen_zero(vmu->dialout)) {
06593 if (!res)
06594 res = ast_play_and_wait(chan, "vm-calldiffnum");
06595 }
06596 } else {
06597 res = ast_play_and_wait(chan, "vm-nonumber");
06598 if (!ast_strlen_zero(vmu->dialout)) {
06599 if (!res)
06600 res = ast_play_and_wait(chan, "vm-toenternumber");
06601 }
06602 }
06603 if (!res)
06604 res = ast_play_and_wait(chan, "vm-star-cancel");
06605 if (!res)
06606 res = ast_waitfordigit(chan, 6000);
06607 if (!res) {
06608 retries++;
06609 if (retries > 3)
06610 res = 't';
06611 }
06612 break;
06613
06614 }
06615 if (res == 't')
06616 res = 0;
06617 else if (res == '*')
06618 res = -1;
06619 }
06620 }
06621
06622 }
06623 else if (option == 1) {
06624
06625 if (!ast_strlen_zero(cid)) {
06626 ast_callerid_parse(cid, &name, &num);
06627 if (!num) {
06628 if (option_verbose > 2)
06629 ast_verbose(VERBOSE_PREFIX_3 "No CID number available, no reply sent\n");
06630 if (!res)
06631 res = ast_play_and_wait(chan, "vm-nonumber");
06632 return res;
06633 } else {
06634 if (find_user(NULL, vmu->context, num)) {
06635 struct leave_vm_options leave_options;
06636 char mailbox[AST_MAX_EXTENSION * 2 + 2];
06637 snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
06638
06639 if (option_verbose > 2)
06640 ast_verbose(VERBOSE_PREFIX_3 "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
06641
06642 memset(&leave_options, 0, sizeof(leave_options));
06643 leave_options.record_gain = record_gain;
06644 res = leave_voicemail(chan, mailbox, &leave_options);
06645 if (!res)
06646 res = 't';
06647 return res;
06648 } else {
06649
06650 if (option_verbose > 2)
06651 ast_verbose( VERBOSE_PREFIX_3 "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
06652 ast_play_and_wait(chan, "vm-nobox");
06653 res = 't';
06654 return res;
06655 }
06656 }
06657 res = 0;
06658 }
06659 }
06660
06661 if (!res) {
06662 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
06663 vms->heard[msg] = 1;
06664 res = wait_file(chan, vms, vms->fn);
06665 }
06666 return res;
06667 }
06668
06669 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
06670 int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
06671 signed char record_gain)
06672 {
06673
06674 int res = 0;
06675 int cmd = 0;
06676 int max_attempts = 3;
06677 int attempts = 0;
06678 int recorded = 0;
06679 int message_exists = 0;
06680 signed char zero_gain = 0;
06681 char *acceptdtmf = "#";
06682 char *canceldtmf = "";
06683
06684
06685
06686
06687 if (duration == NULL) {
06688 ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
06689 return -1;
06690 }
06691
06692 cmd = '3';
06693
06694 while ((cmd >= 0) && (cmd != 't')) {
06695 switch (cmd) {
06696 case '1':
06697 if (!message_exists) {
06698
06699 cmd = '3';
06700 break;
06701 } else {
06702
06703 if (option_verbose > 2)
06704 ast_verbose(VERBOSE_PREFIX_3 "Saving message as is\n");
06705 ast_streamfile(chan, "vm-msgsaved", chan->language);
06706 ast_waitstream(chan, "");
06707 STORE(recordfile, vmu->mailbox, vmu->context, -1);
06708 DISPOSE(recordfile, -1);
06709 cmd = 't';
06710 return res;
06711 }
06712 case '2':
06713
06714 if (option_verbose > 2)
06715 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the message\n");
06716 ast_streamfile(chan, recordfile, chan->language);
06717 cmd = ast_waitstream(chan, AST_DIGIT_ANY);
06718 break;
06719 case '3':
06720 message_exists = 0;
06721
06722 if (recorded == 1) {
06723 if (option_verbose > 2)
06724 ast_verbose(VERBOSE_PREFIX_3 "Re-recording the message\n");
06725 } else {
06726 if (option_verbose > 2)
06727 ast_verbose(VERBOSE_PREFIX_3 "Recording the message\n");
06728 }
06729 if (recorded && outsidecaller) {
06730 cmd = ast_play_and_wait(chan, INTRO);
06731 cmd = ast_play_and_wait(chan, "beep");
06732 }
06733 recorded = 1;
06734
06735 if (record_gain)
06736 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
06737 if (ast_test_flag(vmu, VM_OPERATOR))
06738 canceldtmf = "0";
06739 cmd = ast_play_and_record_full(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
06740 if (record_gain)
06741 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
06742 if (cmd == -1) {
06743
06744 return cmd;
06745 }
06746 if (cmd == '0') {
06747 break;
06748 } else if (cmd == '*') {
06749 break;
06750 }
06751 #if 0
06752 else if (vmu->review && (*duration < 5)) {
06753
06754 if (option_verbose > 2)
06755 ast_verbose(VERBOSE_PREFIX_3 "Message too short\n");
06756 cmd = ast_play_and_wait(chan, "vm-tooshort");
06757 cmd = vm_delete(recordfile);
06758 break;
06759 }
06760 else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
06761
06762 if (option_verbose > 2)
06763 ast_verbose(VERBOSE_PREFIX_3 "Nothing recorded\n");
06764 cmd = vm_delete(recordfile);
06765 cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
06766 if (!cmd)
06767 cmd = ast_play_and_wait(chan, "vm-speakup");
06768 break;
06769 }
06770 #endif
06771 else {
06772
06773 message_exists = 1;
06774 cmd = 0;
06775 }
06776 break;
06777 case '4':
06778 case '5':
06779 case '6':
06780 case '7':
06781 case '8':
06782 case '9':
06783 case '*':
06784 case '#':
06785 cmd = ast_play_and_wait(chan, "vm-sorry");
06786 break;
06787 #if 0
06788
06789
06790 case '*':
06791
06792 cmd = ast_play_and_wait(chan, "vm-deleted");
06793 cmd = vm_delete(recordfile);
06794 if (outsidecaller) {
06795 res = vm_exec(chan, NULL);
06796 return res;
06797 }
06798 else
06799 return 1;
06800 #endif
06801 case '0':
06802 if(!ast_test_flag(vmu, VM_OPERATOR)) {
06803 cmd = ast_play_and_wait(chan, "vm-sorry");
06804 break;
06805 }
06806 if (message_exists || recorded) {
06807 cmd = ast_play_and_wait(chan, "vm-saveoper");
06808 if (!cmd)
06809 cmd = ast_waitfordigit(chan, 3000);
06810 if (cmd == '1') {
06811 ast_play_and_wait(chan, "vm-msgsaved");
06812 cmd = '0';
06813 } else {
06814 ast_play_and_wait(chan, "vm-deleted");
06815 DELETE(recordfile, -1, recordfile);
06816 cmd = '0';
06817 }
06818 }
06819 return cmd;
06820 default:
06821
06822
06823
06824 if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
06825 return cmd;
06826 if (message_exists) {
06827 cmd = ast_play_and_wait(chan, "vm-review");
06828 }
06829 else {
06830 cmd = ast_play_and_wait(chan, "vm-torerecord");
06831 if (!cmd)
06832 cmd = ast_waitfordigit(chan, 600);
06833 }
06834
06835 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
06836 cmd = ast_play_and_wait(chan, "vm-reachoper");
06837 if (!cmd)
06838 cmd = ast_waitfordigit(chan, 600);
06839 }
06840 #if 0
06841 if (!cmd)
06842 cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
06843 #endif
06844 if (!cmd)
06845 cmd = ast_waitfordigit(chan, 6000);
06846 if (!cmd) {
06847 attempts++;
06848 }
06849 if (attempts > max_attempts) {
06850 cmd = 't';
06851 }
06852 }
06853 }
06854 if (outsidecaller)
06855 ast_play_and_wait(chan, "vm-goodbye");
06856 if (cmd == 't')
06857 cmd = 0;
06858 return cmd;
06859 }
06860
06861
06862 int usecount(void)
06863 {
06864 int res;
06865 STANDARD_USECOUNT(res);
06866 return res;
06867 }
06868
06869 char *key()
06870 {
06871 return ASTERISK_GPL_KEY;
06872 }
06873