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
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #include "asterisk.h"
00054
00055 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00056
00057 #include <stdlib.h>
00058 #include <errno.h>
00059 #include <unistd.h>
00060 #include <string.h>
00061 #include <stdlib.h>
00062 #include <stdio.h>
00063 #include <sys/time.h>
00064 #include <sys/stat.h>
00065 #include <sys/types.h>
00066 #include <sys/mman.h>
00067 #include <time.h>
00068 #include <dirent.h>
00069 #ifdef IMAP_STORAGE
00070 #include <ctype.h>
00071 #include <signal.h>
00072 #include <pwd.h>
00073 #include "c-client.h"
00074 #include "imap4r1.h"
00075 #include "linkage.h"
00076 #endif
00077 #include "asterisk/lock.h"
00078 #include "asterisk/file.h"
00079 #include "asterisk/logger.h"
00080 #include "asterisk/channel.h"
00081 #include "asterisk/pbx.h"
00082 #include "asterisk/options.h"
00083 #include "asterisk/config.h"
00084 #include "asterisk/say.h"
00085 #include "asterisk/module.h"
00086 #include "asterisk/adsi.h"
00087 #include "asterisk/app.h"
00088 #include "asterisk/manager.h"
00089 #include "asterisk/dsp.h"
00090 #include "asterisk/localtime.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/utils.h"
00093 #include "asterisk/stringfields.h"
00094 #include "asterisk/smdi.h"
00095 #ifdef ODBC_STORAGE
00096 #include "asterisk/res_odbc.h"
00097 #endif
00098
00099 #ifdef IMAP_STORAGE
00100 AST_MUTEX_DEFINE_STATIC(imaptemp_lock);
00101 static char imaptemp[1024];
00102
00103 static char imapserver[48];
00104 static char imapport[8];
00105 static char imapflags[128];
00106 static char imapfolder[64];
00107 static char authuser[32];
00108 static char authpassword[42];
00109
00110 static int expungeonhangup = 1;
00111 AST_MUTEX_DEFINE_STATIC(delimiter_lock);
00112 static char delimiter = '\0';
00113
00114 struct vm_state;
00115 struct ast_vm_user;
00116
00117 static int init_mailstream (struct vm_state *vms, int box);
00118 static void write_file (char *filename, char *buffer, unsigned long len);
00119
00120 static void display_body (BODY *body, char *pfx, long i);
00121 static char *get_header_by_tag(char *header, char *tag);
00122 static void vm_imap_delete(int msgnum, struct vm_state *vms);
00123 static char *get_user_by_mailbox(char *mailbox);
00124 static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive);
00125 static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive);
00126 static void vmstate_insert(struct vm_state *vms);
00127 static void vmstate_delete(struct vm_state *vms);
00128 static void set_update(MAILSTREAM * stream);
00129 static void init_vm_state(struct vm_state *vms);
00130 static void check_msgArray(struct vm_state *vms);
00131 static void copy_msgArray(struct vm_state *dst, struct vm_state *src);
00132 static int save_body(BODY *body, struct vm_state *vms, char *section, char *format);
00133 static int make_gsm_file(char *dest, char *imapuser, char *dir, int num);
00134 static void get_mailbox_delimiter(MAILSTREAM *stream);
00135 static void mm_parsequota (MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota);
00136 static void imap_mailbox_name(char *spec, struct vm_state *vms, int box, int target);
00137 static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum, struct ast_channel *chan, struct ast_vm_user *vmu, char *fmt, int duration, struct vm_state *vms);
00138 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box);
00139 struct vmstate {
00140 struct vm_state *vms;
00141 struct vmstate *next;
00142 };
00143 AST_MUTEX_DEFINE_STATIC(vmstate_lock);
00144 static struct vmstate *vmstates = NULL;
00145 #endif
00146
00147 #define SMDI_MWI_WAIT_TIMEOUT 1000
00148
00149 #define COMMAND_TIMEOUT 5000
00150
00151 #define VOICEMAIL_DIR_MODE 0777
00152 #define VOICEMAIL_FILE_MODE 0666
00153 #define CHUNKSIZE 65536
00154
00155 #define VOICEMAIL_CONFIG "voicemail.conf"
00156 #define ASTERISK_USERNAME "asterisk"
00157
00158
00159
00160 #define SENDMAIL "/usr/sbin/sendmail -t"
00161
00162 #define INTRO "vm-intro"
00163
00164 #define MAXMSG 100
00165 #define MAXMSGLIMIT 9999
00166
00167 #define BASEMAXINLINE 256
00168 #define BASELINELEN 72
00169 #define BASEMAXINLINE 256
00170 #define eol "\r\n"
00171
00172 #define MAX_DATETIME_FORMAT 512
00173 #define MAX_NUM_CID_CONTEXTS 10
00174
00175 #define VM_REVIEW (1 << 0)
00176 #define VM_OPERATOR (1 << 1)
00177 #define VM_SAYCID (1 << 2)
00178 #define VM_SVMAIL (1 << 3)
00179 #define VM_ENVELOPE (1 << 4)
00180 #define VM_SAYDURATION (1 << 5)
00181 #define VM_SKIPAFTERCMD (1 << 6)
00182 #define VM_FORCENAME (1 << 7)
00183 #define VM_FORCEGREET (1 << 8)
00184 #define VM_PBXSKIP (1 << 9)
00185 #define VM_DIRECFORWARD (1 << 10)
00186 #define VM_ATTACH (1 << 11)
00187 #define VM_DELETE (1 << 12)
00188 #define VM_ALLOCED (1 << 13)
00189 #define VM_SEARCH (1 << 14)
00190 #define VM_TEMPGREETWARN (1 << 15)
00191 #define ERROR_LOCK_PATH -100
00192
00193
00194 enum {
00195 OPT_SILENT = (1 << 0),
00196 OPT_BUSY_GREETING = (1 << 1),
00197 OPT_UNAVAIL_GREETING = (1 << 2),
00198 OPT_RECORDGAIN = (1 << 3),
00199 OPT_PREPEND_MAILBOX = (1 << 4),
00200 OPT_PRIORITY_JUMP = (1 << 5),
00201 OPT_AUTOPLAY = (1 << 6),
00202 } vm_option_flags;
00203
00204 enum {
00205 OPT_ARG_RECORDGAIN = 0,
00206 OPT_ARG_PLAYFOLDER = 1,
00207
00208 OPT_ARG_ARRAY_SIZE = 2,
00209 } vm_option_args;
00210
00211 AST_APP_OPTIONS(vm_app_options, {
00212 AST_APP_OPTION('s', OPT_SILENT),
00213 AST_APP_OPTION('b', OPT_BUSY_GREETING),
00214 AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
00215 AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
00216 AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
00217 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00218 AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER),
00219 });
00220
00221 static int load_config(void);
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 struct baseio {
00303 int iocp;
00304 int iolen;
00305 int linelength;
00306 int ateof;
00307 unsigned char iobuf[BASEMAXINLINE];
00308 };
00309
00310
00311 struct ast_vm_user {
00312 char context[AST_MAX_CONTEXT];
00313 char mailbox[AST_MAX_EXTENSION];
00314 char password[80];
00315 char fullname[80];
00316 char email[80];
00317 char pager[80];
00318 char serveremail[80];
00319 char mailcmd[160];
00320 char language[MAX_LANGUAGE];
00321 char zonetag[80];
00322 char callback[80];
00323 char dialout[80];
00324 char uniqueid[20];
00325 char exit[80];
00326 char attachfmt[20];
00327 unsigned int flags;
00328 int saydurationm;
00329 int maxmsg;
00330 #ifdef IMAP_STORAGE
00331 char imapuser[80];
00332 char imappassword[80];
00333 #endif
00334 double volgain;
00335 AST_LIST_ENTRY(ast_vm_user) list;
00336 };
00337
00338 struct vm_zone {
00339 AST_LIST_ENTRY(vm_zone) list;
00340 char name[80];
00341 char timezone[80];
00342 char msg_format[512];
00343 };
00344
00345 struct vm_state {
00346 char curbox[80];
00347 char username[80];
00348 char curdir[PATH_MAX];
00349 char vmbox[PATH_MAX];
00350 char fn[PATH_MAX];
00351 char fn2[PATH_MAX];
00352 int *deleted;
00353 int *heard;
00354 int curmsg;
00355 int lastmsg;
00356 int newmessages;
00357 int oldmessages;
00358 int starting;
00359 int repeats;
00360 #ifdef IMAP_STORAGE
00361 int updated;
00362 long msgArray[256];
00363 MAILSTREAM *mailstream;
00364 int vmArrayIndex;
00365 char imapuser[80];
00366 int interactive;
00367 unsigned int quota_limit;
00368 unsigned int quota_usage;
00369 struct vm_state *persist_vms;
00370 #endif
00371 };
00372 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain);
00373 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
00374 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
00375 char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
00376 signed char record_gain, struct vm_state *vms);
00377 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
00378 static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
00379 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
00380 static void make_email_file(FILE *p, 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, struct ast_channel *chan, const char *category, int imap);
00381 #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
00382 static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
00383 #endif
00384 static void apply_options(struct ast_vm_user *vmu, const char *options);
00385
00386 #ifdef ODBC_STORAGE
00387 static char odbc_database[80];
00388 static char odbc_table[80];
00389 #define RETRIEVE(a,b) retrieve_file(a,b)
00390 #define DISPOSE(a,b) remove_file(a,b)
00391 #define STORE(a,b,c,d,e,f,g,h,i) store_file(a,b,c,d)
00392 #define EXISTS(a,b,c,d) (message_exists(a,b))
00393 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
00394 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
00395 #define DELETE(a,b,c) (delete_file(a,b))
00396 #else
00397 #ifdef IMAP_STORAGE
00398 #define RETRIEVE(a,b)
00399 #define DISPOSE(a,b)
00400 #define STORE(a,b,c,d,e,f,g,h,i) (imap_store_file(a,b,c,d,e,f,g,h,i))
00401 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00402 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00403 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
00404 #define IMAP_DELETE(a,b,c,d) (vm_imap_delete(b,d))
00405 #define DELETE(a,b,c) (vm_delete(c))
00406 #else
00407 #define RETRIEVE(a,b)
00408 #define DISPOSE(a,b)
00409 #define STORE(a,b,c,d,e,f,g,h,i)
00410 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00411 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00412 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
00413 #define DELETE(a,b,c) (vm_delete(c))
00414 #endif
00415 #endif
00416
00417 static char VM_SPOOL_DIR[PATH_MAX];
00418
00419 static char ext_pass_cmd[128];
00420
00421 int my_umask;
00422
00423 #if ODBC_STORAGE
00424 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
00425 #elif IMAP_STORAGE
00426 #define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
00427 #else
00428 #define tdesc "Comedian Mail (Voicemail System)"
00429 #endif
00430
00431 static char userscontext[AST_MAX_EXTENSION] = "default";
00432
00433 static char *addesc = "Comedian Mail";
00434
00435 static char *synopsis_vm =
00436 "Leave a Voicemail message";
00437
00438 static char *descrip_vm =
00439 " VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
00440 "application allows the calling party to leave a message for the specified\n"
00441 "list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
00442 "be taken from the first mailbox specified. Dialplan execution will stop if the\n"
00443 "specified mailbox does not exist.\n"
00444 " The Voicemail application will exit if any of the following DTMF digits are\n"
00445 "received:\n"
00446 " 0 - Jump to the 'o' extension in the current dialplan context.\n"
00447 " * - Jump to the 'a' extension in the current dialplan context.\n"
00448 " This application will set the following channel variable upon completion:\n"
00449 " VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
00450 " application. The possible values are:\n"
00451 " SUCCESS | USEREXIT | FAILED\n\n"
00452 " Options:\n"
00453 " b - Play the 'busy' greeting to the calling party.\n"
00454 " g(#) - Use the specified amount of gain when recording the voicemail\n"
00455 " message. The units are whole-number decibels (dB).\n"
00456 " s - Skip the playback of instructions for leaving a message to the\n"
00457 " calling party.\n"
00458 " u - Play the 'unavailable' greeting.\n"
00459 " j - Jump to priority n+101 if the mailbox is not found or some other\n"
00460 " error occurs.\n";
00461
00462 static char *synopsis_vmain =
00463 "Check Voicemail messages";
00464
00465 static char *descrip_vmain =
00466 " VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
00467 "calling party to check voicemail messages. A specific mailbox, and optional\n"
00468 "corresponding context, may be specified. If a mailbox is not provided, the\n"
00469 "calling party will be prompted to enter one. If a context is not specified,\n"
00470 "the 'default' context will be used.\n\n"
00471 " Options:\n"
00472 " p - Consider the mailbox parameter as a prefix to the mailbox that\n"
00473 " is entered by the caller.\n"
00474 " g(#) - Use the specified amount of gain when recording a voicemail\n"
00475 " message. The units are whole-number decibels (dB).\n"
00476 " s - Skip checking the passcode for the mailbox.\n"
00477 " a(#) - Skip folder prompt and go directly to folder specified.\n"
00478 " Defaults to INBOX\n";
00479
00480 static char *synopsis_vm_box_exists =
00481 "Check to see if Voicemail mailbox exists";
00482
00483 static char *descrip_vm_box_exists =
00484 " MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
00485 "mailbox exists. If no voicemail context is specified, the 'default' context\n"
00486 "will be used.\n"
00487 " This application will set the following channel variable upon completion:\n"
00488 " VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
00489 " MailboxExists application. Possible values include:\n"
00490 " SUCCESS | FAILED\n\n"
00491 " Options:\n"
00492 " j - Jump to priority n+101 if the mailbox is found.\n";
00493
00494 static char *synopsis_vmauthenticate =
00495 "Authenticate with Voicemail passwords";
00496
00497 static char *descrip_vmauthenticate =
00498 " VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
00499 "same way as the Authenticate application, but the passwords are taken from\n"
00500 "voicemail.conf.\n"
00501 " If the mailbox is specified, only that mailbox's password will be considered\n"
00502 "valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
00503 "be set with the authenticated mailbox.\n\n"
00504 " Options:\n"
00505 " s - Skip playing the initial prompts.\n";
00506
00507
00508 static char *app = "VoiceMail";
00509
00510
00511 static char *app2 = "VoiceMailMain";
00512
00513 static char *app3 = "MailboxExists";
00514 static char *app4 = "VMAuthenticate";
00515
00516 static AST_LIST_HEAD_STATIC(users, ast_vm_user);
00517 static AST_LIST_HEAD_STATIC(zones, vm_zone);
00518 static int maxsilence;
00519 static int maxmsg;
00520 static int silencethreshold = 128;
00521 static char serveremail[80];
00522 static char mailcmd[160];
00523 static char externnotify[160];
00524 static struct ast_smdi_interface *smdi_iface = NULL;
00525 static char vmfmts[80];
00526 static double volgain;
00527 static int vmminmessage;
00528 static int vmmaxmessage;
00529 static int maxgreet;
00530 static int skipms;
00531 static int maxlogins;
00532
00533 static struct ast_flags globalflags = {0};
00534
00535 static int saydurationminfo;
00536
00537 static char dialcontext[AST_MAX_CONTEXT];
00538 static char callcontext[AST_MAX_CONTEXT];
00539 static char exitcontext[AST_MAX_CONTEXT];
00540
00541 static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
00542
00543
00544 static char *emailbody = NULL;
00545 static char *emailsubject = NULL;
00546 static char *pagerbody = NULL;
00547 static char *pagersubject = NULL;
00548 static char fromstring[100];
00549 static char pagerfromstring[100];
00550 static char emailtitle[100];
00551 static char charset[32] = "ISO-8859-1";
00552
00553 static unsigned char adsifdn[4] = "\x00\x00\x00\x0F";
00554 static unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC";
00555 static int adsiver = 1;
00556 static char emaildateformat[32] = "%A, %B %d, %Y at %r";
00557
00558
00559 static void populate_defaults(struct ast_vm_user *vmu)
00560 {
00561 ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
00562 if (saydurationminfo)
00563 vmu->saydurationm = saydurationminfo;
00564 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00565 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00566 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00567 if (maxmsg)
00568 vmu->maxmsg = maxmsg;
00569 vmu->volgain = volgain;
00570 }
00571
00572 static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
00573 {
00574 int x;
00575 if (!strcasecmp(var, "attach")) {
00576 ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00577 } else if (!strcasecmp(var, "attachfmt")) {
00578 ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00579 } else if (!strcasecmp(var, "serveremail")) {
00580 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00581 } else if (!strcasecmp(var, "language")) {
00582 ast_copy_string(vmu->language, value, sizeof(vmu->language));
00583 } else if (!strcasecmp(var, "tz")) {
00584 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00585 #ifdef IMAP_STORAGE
00586 } else if (!strcasecmp(var, "imapuser")) {
00587 ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00588 } else if (!strcasecmp(var, "imappassword")) {
00589 ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00590 #endif
00591 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00592 ast_set2_flag(vmu, ast_true(value), VM_DELETE);
00593 } else if (!strcasecmp(var, "saycid")){
00594 ast_set2_flag(vmu, ast_true(value), VM_SAYCID);
00595 } else if (!strcasecmp(var,"sendvoicemail")){
00596 ast_set2_flag(vmu, ast_true(value), VM_SVMAIL);
00597 } else if (!strcasecmp(var, "review")){
00598 ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00599 } else if (!strcasecmp(var, "tempgreetwarn")){
00600 ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);
00601 } else if (!strcasecmp(var, "operator")){
00602 ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);
00603 } else if (!strcasecmp(var, "envelope")){
00604 ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);
00605 } else if (!strcasecmp(var, "sayduration")){
00606 ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);
00607 } else if (!strcasecmp(var, "saydurationm")){
00608 if (sscanf(value, "%d", &x) == 1) {
00609 vmu->saydurationm = x;
00610 } else {
00611 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
00612 }
00613 } else if (!strcasecmp(var, "forcename")){
00614 ast_set2_flag(vmu, ast_true(value), VM_FORCENAME);
00615 } else if (!strcasecmp(var, "forcegreetings")){
00616 ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);
00617 } else if (!strcasecmp(var, "callback")) {
00618 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00619 } else if (!strcasecmp(var, "dialout")) {
00620 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00621 } else if (!strcasecmp(var, "exitcontext")) {
00622 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00623 } else if (!strcasecmp(var, "maxmsg")) {
00624 vmu->maxmsg = atoi(value);
00625 if (vmu->maxmsg <= 0) {
00626 ast_log(LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %i\n", value, MAXMSG);
00627 vmu->maxmsg = MAXMSG;
00628 } else if (vmu->maxmsg > MAXMSGLIMIT) {
00629 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00630 vmu->maxmsg = MAXMSGLIMIT;
00631 }
00632 } else if (!strcasecmp(var, "volgain")) {
00633 sscanf(value, "%lf", &vmu->volgain);
00634 } else if (!strcasecmp(var, "options")) {
00635 apply_options(vmu, value);
00636 }
00637 }
00638
00639 static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
00640 {
00641 int res;
00642 if (!ast_strlen_zero(vmu->uniqueid)) {
00643 res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, NULL);
00644 if (res > 0) {
00645 ast_copy_string(vmu->password, password, sizeof(vmu->password));
00646 res = 0;
00647 } else if (!res) {
00648 res = -1;
00649 }
00650 return res;
00651 }
00652 return -1;
00653 }
00654
00655 static void apply_options(struct ast_vm_user *vmu, const char *options)
00656 {
00657 char *stringp;
00658 char *s;
00659 char *var, *value;
00660 stringp = ast_strdupa(options);
00661 while ((s = strsep(&stringp, "|"))) {
00662 value = s;
00663 if ((var = strsep(&value, "=")) && value) {
00664 apply_option(vmu, var, value);
00665 }
00666 }
00667 }
00668
00669 static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
00670 {
00671 struct ast_variable *tmp;
00672 tmp = var;
00673 while (tmp) {
00674 if (!strcasecmp(tmp->name, "vmsecret")) {
00675 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00676 } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) {
00677 if (ast_strlen_zero(retval->password))
00678 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00679 } else if (!strcasecmp(tmp->name, "uniqueid")) {
00680 ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00681 } else if (!strcasecmp(tmp->name, "pager")) {
00682 ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
00683 } else if (!strcasecmp(tmp->name, "email")) {
00684 ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
00685 } else if (!strcasecmp(tmp->name, "fullname")) {
00686 ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
00687 } else if (!strcasecmp(tmp->name, "context")) {
00688 ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
00689 #ifdef IMAP_STORAGE
00690 } else if (!strcasecmp(tmp->name, "imapuser")) {
00691 ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
00692 } else if (!strcasecmp(tmp->name, "imappassword")) {
00693 ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
00694 #endif
00695 } else
00696 apply_option(retval, tmp->name, tmp->value);
00697 tmp = tmp->next;
00698 }
00699 }
00700
00701 static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00702 {
00703 struct ast_variable *var;
00704 struct ast_vm_user *retval;
00705
00706 if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
00707 if (!ivm)
00708 ast_set_flag(retval, VM_ALLOCED);
00709 else
00710 memset(retval, 0, sizeof(*retval));
00711 if (mailbox)
00712 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
00713 populate_defaults(retval);
00714 if (!context && ast_test_flag((&globalflags), VM_SEARCH))
00715 var = ast_load_realtime("voicemail", "mailbox", mailbox, NULL);
00716 else
00717 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
00718 if (var) {
00719 apply_options_full(retval, var);
00720 ast_variables_destroy(var);
00721 } else {
00722 if (!ivm)
00723 free(retval);
00724 retval = NULL;
00725 }
00726 }
00727 return retval;
00728 }
00729
00730 static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00731 {
00732
00733 struct ast_vm_user *vmu=NULL, *cur;
00734 AST_LIST_LOCK(&users);
00735
00736 if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
00737 context = "default";
00738
00739 AST_LIST_TRAVERSE(&users, cur, list) {
00740 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
00741 break;
00742 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
00743 break;
00744 }
00745 if (cur) {
00746
00747 if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
00748 memcpy(vmu, cur, sizeof(*vmu));
00749 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
00750 AST_LIST_NEXT(vmu, list) = NULL;
00751 }
00752 } else
00753 vmu = find_user_realtime(ivm, context, mailbox);
00754 AST_LIST_UNLOCK(&users);
00755 return vmu;
00756 }
00757
00758 static int reset_user_pw(const char *context, const char *mailbox, const char *newpass)
00759 {
00760
00761 struct ast_vm_user *cur;
00762 int res = -1;
00763 AST_LIST_LOCK(&users);
00764 AST_LIST_TRAVERSE(&users, cur, list) {
00765 if ((!context || !strcasecmp(context, cur->context)) &&
00766 (!strcasecmp(mailbox, cur->mailbox)))
00767 break;
00768 }
00769 if (cur) {
00770 ast_copy_string(cur->password, newpass, sizeof(cur->password));
00771 res = 0;
00772 }
00773 AST_LIST_UNLOCK(&users);
00774 return res;
00775 }
00776
00777 static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
00778 {
00779 struct ast_config *cfg=NULL;
00780 struct ast_variable *var=NULL;
00781 struct ast_category *cat=NULL;
00782 char *category=NULL, *value=NULL, *new=NULL;
00783 const char *tmp=NULL;
00784
00785 if (!change_password_realtime(vmu, newpassword))
00786 return;
00787
00788
00789 if ((cfg = ast_config_load_with_comments(VOICEMAIL_CONFIG))) {
00790 while ((category = ast_category_browse(cfg, category))) {
00791 if (!strcasecmp(category, vmu->context)) {
00792 tmp = ast_variable_retrieve(cfg, category, vmu->mailbox);
00793 if (!tmp) {
00794 ast_log(LOG_WARNING, "We could not find the mailbox.\n");
00795 break;
00796 }
00797 value = strstr(tmp,",");
00798 if (!value) {
00799 ast_log(LOG_WARNING, "variable has bad format.\n");
00800 break;
00801 }
00802 new = alloca((strlen(value)+strlen(newpassword)+1));
00803 sprintf(new,"%s%s", newpassword, value);
00804 if (!(cat = ast_category_get(cfg, category))) {
00805 ast_log(LOG_WARNING, "Failed to get category structure.\n");
00806 break;
00807 }
00808 ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
00809 }
00810 }
00811
00812 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
00813 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00814 config_text_file_save(VOICEMAIL_CONFIG, cfg, "AppVoicemail");
00815 }
00816 category = NULL;
00817 var = NULL;
00818
00819
00820 if ((cfg = ast_config_load_with_comments("users.conf"))) {
00821 if (option_debug > 3)
00822 ast_log(LOG_DEBUG, "we are looking for %s\n", vmu->mailbox);
00823 while ((category = ast_category_browse(cfg, category))) {
00824 if (option_debug > 3)
00825 ast_log(LOG_DEBUG, "users.conf: %s\n", category);
00826 if (!strcasecmp(category, vmu->mailbox)) {
00827 if (!(tmp = ast_variable_retrieve(cfg, category, "vmsecret"))) {
00828 if (option_debug > 3)
00829 ast_log(LOG_DEBUG, "looks like we need to make vmsecret!\n");
00830 var = ast_variable_new("vmsecret", newpassword);
00831 }
00832 new = alloca(strlen(newpassword)+1);
00833 sprintf(new, "%s", newpassword);
00834 if (!(cat = ast_category_get(cfg, category))) {
00835 if (option_debug > 3)
00836 ast_log(LOG_DEBUG, "failed to get category!\n");
00837 break;
00838 }
00839 if (!var)
00840 ast_variable_update(cat, "vmsecret", new, NULL, 0);
00841 else
00842 ast_variable_append(cat, var);
00843 }
00844 }
00845
00846 reset_user_pw(vmu->context, vmu->mailbox, newpassword);
00847 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00848 config_text_file_save("users.conf", cfg, "AppVoicemail");
00849 }
00850 }
00851
00852 static void vm_change_password_shell(struct ast_vm_user *vmu, char *newpassword)
00853 {
00854 char buf[255];
00855 snprintf(buf,255,"%s %s %s %s",ext_pass_cmd,vmu->context,vmu->mailbox,newpassword);
00856 if (!ast_safe_system(buf))
00857 ast_copy_string(vmu->password, newpassword, sizeof(vmu->password));
00858 }
00859
00860 static int make_dir(char *dest, int len, const char *context, const char *ext, const char *folder)
00861 {
00862 return snprintf(dest, len, "%s%s/%s/%s", VM_SPOOL_DIR, context, ext, folder);
00863 }
00864
00865 #ifdef IMAP_STORAGE
00866 static int make_gsm_file(char *dest, char *imapuser, char *dir, int num)
00867 {
00868 if (mkdir(dir, 01777) && (errno != EEXIST)) {
00869 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
00870 return sprintf(dest, "%s/msg%04d", dir, num);
00871 }
00872
00873 return sprintf(dest, "%s/msg%04d", dir, num);
00874 }
00875
00876 static void vm_imap_delete(int msgnum, struct vm_state *vms)
00877 {
00878 unsigned long messageNum = 0;
00879 char arg[10];
00880
00881
00882
00883
00884 messageNum = vms->msgArray[msgnum];
00885 if (messageNum == 0) {
00886 ast_log(LOG_WARNING, "msgnum %d, mailbox message %lu is zero.\n",msgnum,messageNum);
00887 return;
00888 }
00889 if(option_debug > 2)
00890 ast_log(LOG_DEBUG, "deleting msgnum %d, which is mailbox message %lu\n",msgnum,messageNum);
00891
00892 sprintf (arg,"%lu",messageNum);
00893 mail_setflag (vms->mailstream,arg,"\\DELETED");
00894 }
00895
00896 #endif
00897 static int make_file(char *dest, int len, char *dir, int num)
00898 {
00899 return snprintf(dest, len, "%s/msg%04d", dir, num);
00900 }
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder)
00911 {
00912 mode_t mode = VOICEMAIL_DIR_MODE;
00913
00914 if (!ast_strlen_zero(context)) {
00915 make_dir(dest, len, context, "", "");
00916 if (mkdir(dest, mode) && errno != EEXIST) {
00917 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00918 return -1;
00919 }
00920 }
00921 if (!ast_strlen_zero(ext)) {
00922 make_dir(dest, len, context, ext, "");
00923 if (mkdir(dest, mode) && errno != EEXIST) {
00924 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00925 return -1;
00926 }
00927 }
00928 if (!ast_strlen_zero(folder)) {
00929 make_dir(dest, len, context, ext, folder);
00930 if (mkdir(dest, mode) && errno != EEXIST) {
00931 ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno));
00932 return -1;
00933 }
00934 }
00935 return 0;
00936 }
00937
00938
00939
00940
00941 static int vm_lock_path(const char *path)
00942 {
00943 switch (ast_lock_path(path)) {
00944 case AST_LOCK_TIMEOUT:
00945 return -1;
00946 default:
00947 return 0;
00948 }
00949 }
00950
00951
00952 #ifdef ODBC_STORAGE
00953 struct generic_prepare_struct {
00954 char *sql;
00955 int argc;
00956 char **argv;
00957 };
00958
00959 static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
00960 {
00961 struct generic_prepare_struct *gps = data;
00962 int res, i;
00963 SQLHSTMT stmt;
00964
00965 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00966 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00967 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00968 return NULL;
00969 }
00970 res = SQLPrepare(stmt, (unsigned char *)gps->sql, SQL_NTS);
00971 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00972 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", gps->sql);
00973 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00974 return NULL;
00975 }
00976 for (i = 0; i < gps->argc; i++)
00977 SQLBindParameter(stmt, i + 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(gps->argv[i]), 0, gps->argv[i], 0, NULL);
00978
00979 return stmt;
00980 }
00981
00982 static int retrieve_file(char *dir, int msgnum)
00983 {
00984 int x = 0;
00985 int res;
00986 int fd=-1;
00987 size_t fdlen = 0;
00988 void *fdm = MAP_FAILED;
00989 SQLSMALLINT colcount=0;
00990 SQLHSTMT stmt;
00991 char sql[PATH_MAX];
00992 char fmt[80]="";
00993 char *c;
00994 char coltitle[256];
00995 SQLSMALLINT collen;
00996 SQLSMALLINT datatype;
00997 SQLSMALLINT decimaldigits;
00998 SQLSMALLINT nullable;
00999 SQLULEN colsize;
01000 SQLLEN colsize2;
01001 FILE *f=NULL;
01002 char rowdata[80];
01003 char fn[PATH_MAX];
01004 char full_fn[PATH_MAX];
01005 char msgnums[80];
01006 char *argv[] = { dir, msgnums };
01007 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
01008
01009 struct odbc_obj *obj;
01010 obj = ast_odbc_request_obj(odbc_database, 0);
01011 if (obj) {
01012 ast_copy_string(fmt, vmfmts, sizeof(fmt));
01013 c = strchr(fmt, '|');
01014 if (c)
01015 *c = '\0';
01016 if (!strcasecmp(fmt, "wav49"))
01017 strcpy(fmt, "WAV");
01018 snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
01019 if (msgnum > -1)
01020 make_file(fn, sizeof(fn), dir, msgnum);
01021 else
01022 ast_copy_string(fn, dir, sizeof(fn));
01023 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
01024
01025 if (!(f = fopen(full_fn, "w+"))) {
01026 ast_log(LOG_WARNING, "Failed to open/create '%s'\n", full_fn);
01027 goto yuck;
01028 }
01029
01030 snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
01031 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?",odbc_table);
01032 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01033 if (!stmt) {
01034 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01035 ast_odbc_release_obj(obj);
01036 goto yuck;
01037 }
01038 res = SQLFetch(stmt);
01039 if (res == SQL_NO_DATA) {
01040 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01041 ast_odbc_release_obj(obj);
01042 goto yuck;
01043 }
01044 else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01045 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
01046 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01047 ast_odbc_release_obj(obj);
01048 goto yuck;
01049 }
01050 fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, 0770);
01051 if (fd < 0) {
01052 ast_log(LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno));
01053 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01054 ast_odbc_release_obj(obj);
01055 goto yuck;
01056 }
01057 res = SQLNumResultCols(stmt, &colcount);
01058 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01059 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
01060 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01061 ast_odbc_release_obj(obj);
01062 goto yuck;
01063 }
01064 if (f)
01065 fprintf(f, "[message]\n");
01066 for (x=0;x<colcount;x++) {
01067 rowdata[0] = '\0';
01068 collen = sizeof(coltitle);
01069 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen,
01070 &datatype, &colsize, &decimaldigits, &nullable);
01071 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01072 ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
01073 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01074 ast_odbc_release_obj(obj);
01075 goto yuck;
01076 }
01077 if (!strcasecmp(coltitle, "recording")) {
01078 off_t offset;
01079 res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2);
01080 fdlen = colsize2;
01081 if (fd > -1) {
01082 char tmp[1]="";
01083 lseek(fd, fdlen - 1, SEEK_SET);
01084 if (write(fd, tmp, 1) != 1) {
01085 close(fd);
01086 fd = -1;
01087 continue;
01088 }
01089
01090 for (offset = 0; offset < colsize2; offset += CHUNKSIZE) {
01091 if ((fdm = mmap(NULL, CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) {
01092 ast_log(LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno);
01093 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
01094 ast_odbc_release_obj(obj);
01095 goto yuck;
01096 } else {
01097 res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL);
01098 munmap(fdm, CHUNKSIZE);
01099 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01100 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01101 unlink(full_fn);
01102 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
01103 ast_odbc_release_obj(obj);
01104 goto yuck;
01105 }
01106 }
01107 }
01108 truncate(full_fn, fdlen);
01109 }
01110 } else {
01111 res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
01112 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01113 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01114 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01115 ast_odbc_release_obj(obj);
01116 goto yuck;
01117 }
01118 if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
01119 fprintf(f, "%s=%s\n", coltitle, rowdata);
01120 }
01121 }
01122 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01123 ast_odbc_release_obj(obj);
01124 } else
01125 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01126 yuck:
01127 if (f)
01128 fclose(f);
01129 if (fd > -1)
01130 close(fd);
01131 return x - 1;
01132 }
01133
01134 static int remove_file(char *dir, int msgnum)
01135 {
01136 char fn[PATH_MAX];
01137 char full_fn[PATH_MAX];
01138 char msgnums[80];
01139
01140 if (msgnum > -1) {
01141 snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
01142 make_file(fn, sizeof(fn), dir, msgnum);
01143 } else
01144 ast_copy_string(fn, dir, sizeof(fn));
01145 ast_filedelete(fn, NULL);
01146 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
01147 unlink(full_fn);
01148 return 0;
01149 }
01150
01151 static int last_message_index(struct ast_vm_user *vmu, char *dir)
01152 {
01153 int x = 0;
01154 int res;
01155 SQLHSTMT stmt;
01156 char sql[PATH_MAX];
01157 char rowdata[20];
01158 char *argv[] = { dir };
01159 struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv };
01160
01161 struct odbc_obj *obj;
01162 obj = ast_odbc_request_obj(odbc_database, 0);
01163 if (obj) {
01164 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?",odbc_table);
01165 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01166 if (!stmt) {
01167 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01168 ast_odbc_release_obj(obj);
01169 goto yuck;
01170 }
01171 res = SQLFetch(stmt);
01172 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01173 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
01174 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01175 ast_odbc_release_obj(obj);
01176 goto yuck;
01177 }
01178 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
01179 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01180 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01181 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01182 ast_odbc_release_obj(obj);
01183 goto yuck;
01184 }
01185 if (sscanf(rowdata, "%d", &x) != 1)
01186 ast_log(LOG_WARNING, "Failed to read message count!\n");
01187 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01188 ast_odbc_release_obj(obj);
01189 } else
01190 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01191 yuck:
01192 return x - 1;
01193 }
01194
01195 static int message_exists(char *dir, int msgnum)
01196 {
01197 int x = 0;
01198 int res;
01199 SQLHSTMT stmt;
01200 char sql[PATH_MAX];
01201 char rowdata[20];
01202 char msgnums[20];
01203 char *argv[] = { dir, msgnums };
01204 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
01205
01206 struct odbc_obj *obj;
01207 obj = ast_odbc_request_obj(odbc_database, 0);
01208 if (obj) {
01209 snprintf(msgnums, sizeof(msgnums), "%d", msgnum);
01210 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?",odbc_table);
01211 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01212 if (!stmt) {
01213 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01214 ast_odbc_release_obj(obj);
01215 goto yuck;
01216 }
01217 res = SQLFetch(stmt);
01218 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01219 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
01220 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01221 ast_odbc_release_obj(obj);
01222 goto yuck;
01223 }
01224 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
01225 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01226 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
01227 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01228 ast_odbc_release_obj(obj);
01229 goto yuck;
01230 }
01231 if (sscanf(rowdata, "%d", &x) != 1)
01232 ast_log(LOG_WARNING, "Failed to read message count!\n");
01233 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01234 ast_odbc_release_obj(obj);
01235 } else
01236 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01237 yuck:
01238 return x;
01239 }
01240
01241 static int count_messages(struct ast_vm_user *vmu, char *dir)
01242 {
01243 return last_message_index(vmu, dir) + 1;
01244 }
01245
01246 static void delete_file(char *sdir, int smsg)
01247 {
01248 SQLHSTMT stmt;
01249 char sql[PATH_MAX];
01250 char msgnums[20];
01251 char *argv[] = { sdir, msgnums };
01252 struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv };
01253
01254 struct odbc_obj *obj;
01255 obj = ast_odbc_request_obj(odbc_database, 0);
01256 if (obj) {
01257 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01258 snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?",odbc_table);
01259 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01260 if (!stmt)
01261 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01262 else
01263 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01264 ast_odbc_release_obj(obj);
01265 } else
01266 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01267 return;
01268 }
01269
01270 static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext)
01271 {
01272 SQLHSTMT stmt;
01273 char sql[512];
01274 char msgnums[20];
01275 char msgnumd[20];
01276 struct odbc_obj *obj;
01277 char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums };
01278 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
01279
01280 delete_file(ddir, dmsg);
01281 obj = ast_odbc_request_obj(odbc_database, 0);
01282 if (obj) {
01283 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01284 snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
01285 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);
01286 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01287 if (!stmt)
01288 ast_log(LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql);
01289 else
01290 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
01291 ast_odbc_release_obj(obj);
01292 } else
01293 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01294 return;
01295 }
01296
01297 static int store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum)
01298 {
01299 int x = 0;
01300 int res;
01301 int fd = -1;
01302 void *fdm = MAP_FAILED;
01303 size_t fdlen = -1;
01304 SQLHSTMT stmt;
01305 SQLLEN len;
01306 char sql[PATH_MAX];
01307 char msgnums[20];
01308 char fn[PATH_MAX];
01309 char full_fn[PATH_MAX];
01310 char fmt[80]="";
01311 char *c;
01312 const char *context="", *macrocontext="", *callerid="", *origtime="", *duration="";
01313 const char *category = "";
01314 struct ast_config *cfg=NULL;
01315 struct odbc_obj *obj;
01316
01317 delete_file(dir, msgnum);
01318 obj = ast_odbc_request_obj(odbc_database, 0);
01319 if (obj) {
01320 ast_copy_string(fmt, vmfmts, sizeof(fmt));
01321 c = strchr(fmt, '|');
01322 if (c)
01323 *c = '\0';
01324 if (!strcasecmp(fmt, "wav49"))
01325 strcpy(fmt, "WAV");
01326 snprintf(msgnums, sizeof(msgnums),"%d", msgnum);
01327 if (msgnum > -1)
01328 make_file(fn, sizeof(fn), dir, msgnum);
01329 else
01330 ast_copy_string(fn, dir, sizeof(fn));
01331 snprintf(full_fn, sizeof(full_fn), "%s.txt", fn);
01332 cfg = ast_config_load(full_fn);
01333 snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt);
01334 fd = open(full_fn, O_RDWR);
01335 if (fd < 0) {
01336 ast_log(LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno));
01337 ast_odbc_release_obj(obj);
01338 goto yuck;
01339 }
01340 if (cfg) {
01341 context = ast_variable_retrieve(cfg, "message", "context");
01342 if (!context) context = "";
01343 macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext");
01344 if (!macrocontext) macrocontext = "";
01345 callerid = ast_variable_retrieve(cfg, "message", "callerid");
01346 if (!callerid) callerid = "";
01347 origtime = ast_variable_retrieve(cfg, "message", "origtime");
01348 if (!origtime) origtime = "";
01349 duration = ast_variable_retrieve(cfg, "message", "duration");
01350 if (!duration) duration = "";
01351 category = ast_variable_retrieve(cfg, "message", "category");
01352 if (!category) category = "";
01353 }
01354 fdlen = lseek(fd, 0, SEEK_END);
01355 lseek(fd, 0, SEEK_SET);
01356 printf("Length is %zd\n", fdlen);
01357 fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0);
01358 if (fdm == MAP_FAILED) {
01359 ast_log(LOG_WARNING, "Memory map failed!\n");
01360 ast_odbc_release_obj(obj);
01361 goto yuck;
01362 }
01363 res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
01364 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01365 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
01366 ast_odbc_release_obj(obj);
01367 goto yuck;
01368 }
01369 if (!ast_strlen_zero(category))
01370 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,category) VALUES (?,?,?,?,?,?,?,?,?,?,?)",odbc_table);
01371 else
01372 snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext) VALUES (?,?,?,?,?,?,?,?,?,?)",odbc_table);
01373 res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
01374 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01375 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
01376 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01377 ast_odbc_release_obj(obj);
01378 goto yuck;
01379 }
01380 len = fdlen;
01381 SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
01382 SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(msgnums), 0, (void *)msgnums, 0, NULL);
01383 SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, fdlen, 0, (void *)fdm, fdlen, &len);
01384 SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(context), 0, (void *)context, 0, NULL);
01385 SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(macrocontext), 0, (void *)macrocontext, 0, NULL);
01386 SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(callerid), 0, (void *)callerid, 0, NULL);
01387 SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(origtime), 0, (void *)origtime, 0, NULL);
01388 SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(duration), 0, (void *)duration, 0, NULL);
01389 SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxuser), 0, (void *)mailboxuser, 0, NULL);
01390 SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(mailboxcontext), 0, (void *)mailboxcontext, 0, NULL);
01391 if (!ast_strlen_zero(category))
01392 SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(category), 0, (void *)category, 0, NULL);
01393 res = ast_odbc_smart_execute(obj, stmt);
01394 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
01395 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01396 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01397 ast_odbc_release_obj(obj);
01398 goto yuck;
01399 }
01400 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
01401 ast_odbc_release_obj(obj);
01402 } else
01403 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01404 yuck:
01405 if (cfg)
01406 ast_config_destroy(cfg);
01407 if (fdm != MAP_FAILED)
01408 munmap(fdm, fdlen);
01409 if (fd > -1)
01410 close(fd);
01411 return x;
01412 }
01413
01414 static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg)
01415 {
01416 SQLHSTMT stmt;
01417 char sql[PATH_MAX];
01418 char msgnums[20];
01419 char msgnumd[20];
01420 struct odbc_obj *obj;
01421 char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums };
01422 struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv };
01423
01424 delete_file(ddir, dmsg);
01425 obj = ast_odbc_request_obj(odbc_database, 0);
01426 if (obj) {
01427 snprintf(msgnums, sizeof(msgnums), "%d", smsg);
01428 snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg);
01429 snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?",odbc_table);
01430 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
01431 if (!stmt)
01432 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
01433 else
01434 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
01435 ast_odbc_release_obj(obj);
01436 } else
01437 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
01438 return;
01439 }
01440
01441 #else
01442 #ifndef IMAP_STORAGE
01443 static int count_messages(struct ast_vm_user *vmu, char *dir)
01444 {
01445
01446
01447 int vmcount = 0;
01448 DIR *vmdir = NULL;
01449 struct dirent *vment = NULL;
01450
01451 if (vm_lock_path(dir))
01452 return ERROR_LOCK_PATH;
01453
01454 if ((vmdir = opendir(dir))) {
01455 while ((vment = readdir(vmdir))) {
01456 if (strlen(vment->d_name) > 7 && !strncmp(vment->d_name + 7, ".txt", 4))
01457 vmcount++;
01458 }
01459 closedir(vmdir);
01460 }
01461 ast_unlock_path(dir);
01462
01463 return vmcount;
01464 }
01465
01466 static void rename_file(char *sfn, char *dfn)
01467 {
01468 char stxt[PATH_MAX];
01469 char dtxt[PATH_MAX];
01470 ast_filerename(sfn,dfn,NULL);
01471 snprintf(stxt, sizeof(stxt), "%s.txt", sfn);
01472 snprintf(dtxt, sizeof(dtxt), "%s.txt", dfn);
01473 rename(stxt, dtxt);
01474 }
01475
01476 static int copy(char *infile, char *outfile)
01477 {
01478 int ifd;
01479 int ofd;
01480 int res;
01481 int len;
01482 char buf[4096];
01483
01484 #ifdef HARDLINK_WHEN_POSSIBLE
01485
01486 if (link(infile, outfile)) {
01487 #endif
01488 if ((ifd = open(infile, O_RDONLY)) < 0) {
01489 ast_log(LOG_WARNING, "Unable to open %s in read-only mode\n", infile);
01490 return -1;
01491 }
01492 if ((ofd = open(outfile, O_WRONLY | O_TRUNC | O_CREAT, VOICEMAIL_FILE_MODE)) < 0) {
01493 ast_log(LOG_WARNING, "Unable to open %s in write-only mode\n", outfile);
01494 close(ifd);
01495 return -1;
01496 }
01497 do {
01498 len = read(ifd, buf, sizeof(buf));
01499 if (len < 0) {
01500 ast_log(LOG_WARNING, "Read failed on %s: %s\n", infile, strerror(errno));
01501 close(ifd);
01502 close(ofd);
01503 unlink(outfile);
01504 }
01505 if (len) {
01506 res = write(ofd, buf, len);
01507 if (errno == ENOMEM || errno == ENOSPC || res != len) {
01508 ast_log(LOG_WARNING, "Write failed on %s (%d of %d): %s\n", outfile, res, len, strerror(errno));
01509 close(ifd);
01510 close(ofd);
01511 unlink(outfile);
01512 }
01513 }
01514 } while (len);
01515 close(ifd);
01516 close(ofd);
01517 return 0;
01518 #ifdef HARDLINK_WHEN_POSSIBLE
01519 } else {
01520
01521 return 0;
01522 }
01523 #endif
01524 }
01525
01526 static void copy_file(char *frompath, char *topath)
01527 {
01528 char frompath2[PATH_MAX], topath2[PATH_MAX];
01529 ast_filecopy(frompath, topath, NULL);
01530 snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
01531 snprintf(topath2, sizeof(topath2), "%s.txt", topath);
01532 copy(frompath2, topath2);
01533 }
01534 #endif
01535
01536
01537
01538 #if (!defined(IMAP_STORAGE) && !defined(ODBC_STORAGE))
01539 static int last_message_index(struct ast_vm_user *vmu, char *dir)
01540 {
01541 int x;
01542 char fn[PATH_MAX];
01543
01544 if (vm_lock_path(dir))
01545 return ERROR_LOCK_PATH;
01546
01547 for (x = 0; x < vmu->maxmsg; x++) {
01548 make_file(fn, sizeof(fn), dir, x);
01549 if (ast_fileexists(fn, NULL, NULL) < 1)
01550 break;
01551 }
01552 ast_unlock_path(dir);
01553
01554 return x - 1;
01555 }
01556 #endif
01557 #endif
01558
01559 #ifndef ODBC_STORAGE
01560 static int vm_delete(char *file)
01561 {
01562 char *txt;
01563 int txtsize = 0;
01564
01565 txtsize = (strlen(file) + 5)*sizeof(char);
01566 txt = alloca(txtsize);
01567
01568
01569
01570 snprintf(txt, txtsize, "%s.txt", file);
01571 unlink(txt);
01572 return ast_filedelete(file, NULL);
01573 }
01574 #endif
01575
01576 static int inbuf(struct baseio *bio, FILE *fi)
01577 {
01578 int l;
01579
01580 if (bio->ateof)
01581 return 0;
01582
01583 if ((l = fread(bio->iobuf,1,BASEMAXINLINE,fi)) <= 0) {
01584 if (ferror(fi))
01585 return -1;
01586
01587 bio->ateof = 1;
01588 return 0;
01589 }
01590
01591 bio->iolen= l;
01592 bio->iocp= 0;
01593
01594 return 1;
01595 }
01596
01597 static int inchar(struct baseio *bio, FILE *fi)
01598 {
01599 if (bio->iocp>=bio->iolen) {
01600 if (!inbuf(bio, fi))
01601 return EOF;
01602 }
01603
01604 return bio->iobuf[bio->iocp++];
01605 }
01606
01607 static int ochar(struct baseio *bio, int c, FILE *so)
01608 {
01609 if (bio->linelength>=BASELINELEN) {
01610 if (fputs(eol,so)==EOF)
01611 return -1;
01612
01613 bio->linelength= 0;
01614 }
01615
01616 if (putc(((unsigned char)c),so)==EOF)
01617 return -1;
01618
01619 bio->linelength++;
01620
01621 return 1;
01622 }
01623
01624 static int base_encode(char *filename, FILE *so)
01625 {
01626 unsigned char dtable[BASEMAXINLINE];
01627 int i,hiteof= 0;
01628 FILE *fi;
01629 struct baseio bio;
01630
01631 memset(&bio, 0, sizeof(bio));
01632 bio.iocp = BASEMAXINLINE;
01633
01634 if (!(fi = fopen(filename, "rb"))) {
01635 ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
01636 return -1;
01637 }
01638
01639 for (i= 0;i<9;i++) {
01640 dtable[i]= 'A'+i;
01641 dtable[i+9]= 'J'+i;
01642 dtable[26+i]= 'a'+i;
01643 dtable[26+i+9]= 'j'+i;
01644 }
01645 for (i= 0;i<8;i++) {
01646 dtable[i+18]= 'S'+i;
01647 dtable[26+i+18]= 's'+i;
01648 }
01649 for (i= 0;i<10;i++) {
01650 dtable[52+i]= '0'+i;
01651 }
01652 dtable[62]= '+';
01653 dtable[63]= '/';
01654
01655 while (!hiteof){
01656 unsigned char igroup[3],ogroup[4];
01657 int c,n;
01658
01659 igroup[0]= igroup[1]= igroup[2]= 0;
01660
01661 for (n= 0;n<3;n++) {
01662 if ((c = inchar(&bio, fi)) == EOF) {
01663 hiteof= 1;
01664 break;
01665 }
01666
01667 igroup[n]= (unsigned char)c;
01668 }
01669
01670 if (n> 0) {
01671 ogroup[0]= dtable[igroup[0]>>2];
01672 ogroup[1]= dtable[((igroup[0]&3)<<4)|(igroup[1]>>4)];
01673 ogroup[2]= dtable[((igroup[1]&0xF)<<2)|(igroup[2]>>6)];
01674 ogroup[3]= dtable[igroup[2]&0x3F];
01675
01676 if (n<3) {
01677 ogroup[3]= '=';
01678
01679 if (n<2)
01680 ogroup[2]= '=';
01681 }
01682
01683 for (i= 0;i<4;i++)
01684 ochar(&bio, ogroup[i], so);
01685 }
01686 }
01687
01688 if (fputs(eol,so)==EOF)
01689 return 0;
01690
01691 fclose(fi);
01692
01693 return 1;
01694 }
01695
01696 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, const char *category)
01697 {
01698 char callerid[256];
01699
01700 pbx_builtin_setvar_helper(ast, "VM_NAME", vmu->fullname);
01701 pbx_builtin_setvar_helper(ast, "VM_DUR", dur);
01702 snprintf(passdata, passdatasize, "%d", msgnum);
01703 pbx_builtin_setvar_helper(ast, "VM_MSGNUM", passdata);
01704 pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context);
01705 pbx_builtin_setvar_helper(ast, "VM_MAILBOX", mailbox);
01706 pbx_builtin_setvar_helper(ast, "VM_CALLERID", ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, "Unknown Caller"));
01707 pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (cidname ? cidname : "an unknown caller"));
01708 pbx_builtin_setvar_helper(ast, "VM_CIDNUM", (cidnum ? cidnum : "an unknown caller"));
01709 pbx_builtin_setvar_helper(ast, "VM_DATE", date);
01710 pbx_builtin_setvar_helper(ast, "VM_CATEGORY", category ? ast_strdupa(category) : "no category");
01711 }
01712
01713 static char *quote(const char *from, char *to, size_t len)
01714 {
01715 char *ptr = to;
01716 *ptr++ = '"';
01717 for (; ptr < to + len - 1; from++) {
01718 if (*from == '"')
01719 *ptr++ = '\\';
01720 else if (*from == '\0')
01721 break;
01722 *ptr++ = *from;
01723 }
01724 if (ptr < to + len - 1)
01725 *ptr++ = '"';
01726 *ptr = '\0';
01727 return to;
01728 }
01729
01730
01731
01732
01733 static const struct tm *vmu_tm(const struct ast_vm_user *vmu, struct tm *tm)
01734 {
01735 const struct vm_zone *z = NULL;
01736 time_t t = time(NULL);
01737
01738
01739 if (!ast_strlen_zero(vmu->zonetag)) {
01740
01741 AST_LIST_LOCK(&zones);
01742 AST_LIST_TRAVERSE(&zones, z, list) {
01743 if (!strcmp(z->name, vmu->zonetag))
01744 break;
01745 }
01746 AST_LIST_UNLOCK(&zones);
01747 }
01748 ast_localtime(&t, tm, z ? z->timezone : NULL);
01749 return tm;
01750 }
01751
01752
01753 static FILE *vm_mkftemp(char *template)
01754 {
01755 FILE *p = NULL;
01756 int pfd = mkstemp(template);
01757 chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
01758 if (pfd > -1) {
01759 p = fdopen(pfd, "w+");
01760 if (!p) {
01761 close(pfd);
01762 pfd = -1;
01763 }
01764 }
01765 return p;
01766 }
01767
01768 static void make_email_file(FILE *p, 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, struct ast_channel *chan, const char *category, int imap)
01769 {
01770 char date[256];
01771 char host[MAXHOSTNAMELEN] = "";
01772 char who[256];
01773 char bound[256];
01774 char fname[256];
01775 char dur[256];
01776 char tmpcmd[256];
01777 struct tm tm;
01778 char *passdata2;
01779 size_t len_passdata;
01780 #ifdef IMAP_STORAGE
01781 #define ENDL "\r\n"
01782 #else
01783 #define ENDL "\n"
01784 #endif
01785
01786 gethostname(host, sizeof(host) - 1);
01787 if (strchr(srcemail, '@'))
01788 ast_copy_string(who, srcemail, sizeof(who));
01789 else {
01790 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
01791 }
01792 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01793 strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
01794 fprintf(p, "Date: %s" ENDL, date);
01795
01796
01797 strftime(date, sizeof(date), emaildateformat, &tm);
01798
01799 if (*fromstring) {
01800 struct ast_channel *ast;
01801 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
01802 char *passdata;
01803 int vmlen = strlen(fromstring)*3 + 200;
01804 if ((passdata = alloca(vmlen))) {
01805 memset(passdata, 0, vmlen);
01806 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
01807 pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
01808 len_passdata = strlen(passdata) * 2 + 3;
01809 passdata2 = alloca(len_passdata);
01810 fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata), who);
01811 } else
01812 ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01813 ast_channel_free(ast);
01814 } else
01815 ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01816 } else
01817 fprintf(p, "From: Asterisk PBX <%s>" ENDL, who);
01818 len_passdata = strlen(vmu->fullname) * 2 + 3;
01819 passdata2 = alloca(len_passdata);
01820 fprintf(p, "To: %s <%s>" ENDL, quote(vmu->fullname, passdata2, len_passdata), vmu->email);
01821 if (emailsubject) {
01822 struct ast_channel *ast;
01823 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
01824 char *passdata;
01825 int vmlen = strlen(emailsubject)*3 + 200;
01826 if ((passdata = alloca(vmlen))) {
01827 memset(passdata, 0, vmlen);
01828 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
01829 pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
01830 fprintf(p, "Subject: %s" ENDL, passdata);
01831 } else
01832 ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01833 ast_channel_free(ast);
01834 } else
01835 ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01836 } else if (*emailtitle) {
01837 fprintf(p, emailtitle, msgnum + 1, mailbox) ;
01838 fprintf(p, ENDL) ;
01839 } else if (ast_test_flag((&globalflags), VM_PBXSKIP))
01840 fprintf(p, "Subject: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
01841 else
01842 fprintf(p, "Subject: [PBX]: New message %d in mailbox %s" ENDL, msgnum + 1, mailbox);
01843 fprintf(p, "Message-ID: <Asterisk-%d-%d-%s-%d@%s>" ENDL, msgnum + 1, (unsigned int)ast_random(), mailbox, (int)getpid(), host);
01844 if(imap) {
01845
01846 fprintf(p, "X-Asterisk-VM-Message-Num: %d" ENDL, msgnum + 1);
01847
01848 fprintf(p, "X-Asterisk-VM-Server-Name: %s" ENDL, fromstring);
01849 fprintf(p, "X-Asterisk-VM-Context: %s" ENDL, context);
01850 fprintf(p, "X-Asterisk-VM-Extension: %s" ENDL, mailbox);
01851 fprintf(p, "X-Asterisk-VM-Priority: %d" ENDL, chan->priority);
01852 fprintf(p, "X-Asterisk-VM-Caller-channel: %s" ENDL, chan->name);
01853 fprintf(p, "X-Asterisk-VM-Caller-ID-Num: %s" ENDL, cidnum);
01854 fprintf(p, "X-Asterisk-VM-Caller-ID-Name: %s" ENDL, cidname);
01855 fprintf(p, "X-Asterisk-VM-Duration: %d" ENDL, duration);
01856 if (!ast_strlen_zero(category))
01857 fprintf(p, "X-Asterisk-VM-Category: %s" ENDL, category);
01858 fprintf(p, "X-Asterisk-VM-Orig-date: %s" ENDL, date);
01859 fprintf(p, "X-Asterisk-VM-Orig-time: %ld" ENDL, (long)time(NULL));
01860 }
01861 if (!ast_strlen_zero(cidnum))
01862 fprintf(p, "X-Asterisk-CallerID: %s" ENDL, cidnum);
01863 if (!ast_strlen_zero(cidname))
01864 fprintf(p, "X-Asterisk-CallerIDName: %s" ENDL, cidname);
01865 fprintf(p, "MIME-Version: 1.0" ENDL);
01866 if (attach_user_voicemail) {
01867
01868 snprintf(bound, sizeof(bound), "----voicemail_%d%s%d%d", msgnum + 1, mailbox, (int)getpid(), (unsigned int)ast_random());
01869
01870 fprintf(p, "Content-Type: multipart/mixed; boundary=\"%s\"" ENDL, bound);
01871 fprintf(p, ENDL ENDL "This is a multi-part message in MIME format." ENDL ENDL);
01872 fprintf(p, "--%s" ENDL, bound);
01873 }
01874 fprintf(p, "Content-Type: text/plain; charset=%s" ENDL "Content-Transfer-Encoding: 8bit" ENDL ENDL, charset);
01875 if (emailbody) {
01876 struct ast_channel *ast;
01877 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
01878 char *passdata;
01879 int vmlen = strlen(emailbody)*3 + 200;
01880 if ((passdata = alloca(vmlen))) {
01881 memset(passdata, 0, vmlen);
01882 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
01883 pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
01884 fprintf(p, "%s" ENDL, passdata);
01885 } else
01886 ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
01887 ast_channel_free(ast);
01888 } else
01889 ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
01890 } else {
01891 fprintf(p, "Dear %s:" ENDL ENDL "\tJust wanted to let you know you were just left a %s long message (number %d)" ENDL
01892
01893 "in mailbox %s from %s, on %s so you might" ENDL
01894 "want to check it when you get a chance. Thanks!" ENDL ENDL "\t\t\t\t--Asterisk" ENDL ENDL, vmu->fullname,
01895 dur, msgnum + 1, mailbox, (cidname ? cidname : (cidnum ? cidnum : "an unknown caller")), date);
01896 }
01897 if (attach_user_voicemail) {
01898
01899 char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
01900 char tmpdir[256], newtmp[256];
01901 int tmpfd = -1;
01902
01903 if (vmu->volgain < -.001 || vmu->volgain > .001) {
01904 create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
01905 snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir);
01906 tmpfd = mkstemp(newtmp);
01907 chmod(newtmp, VOICEMAIL_FILE_MODE & ~my_umask);
01908 if (option_debug > 2)
01909 ast_log(LOG_DEBUG, "newtmp: %s\n", newtmp);
01910 if (tmpfd > -1) {
01911 snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format);
01912 ast_safe_system(tmpcmd);
01913 attach = newtmp;
01914 if (option_debug > 2)
01915 ast_log(LOG_DEBUG, "VOLGAIN: Stored at: %s.%s - Level: %.4f - Mailbox: %s\n", attach, format, vmu->volgain, mailbox);
01916 }
01917 }
01918 fprintf(p, "--%s" ENDL, bound);
01919 fprintf(p, "Content-Type: %s%s; name=\"msg%04d.%s\"" ENDL, ctype, format, msgnum + 1, format);
01920 fprintf(p, "Content-Transfer-Encoding: base64" ENDL);
01921 fprintf(p, "Content-Description: Voicemail sound attachment." ENDL);
01922 fprintf(p, "Content-Disposition: attachment; filename=\"msg%04d.%s\"" ENDL ENDL, msgnum + 1, format);
01923 snprintf(fname, sizeof(fname), "%s.%s", attach, format);
01924 base_encode(fname, p);
01925 fprintf(p, ENDL "--%s--" ENDL "." ENDL, bound);
01926 if (tmpfd > -1) {
01927 unlink(fname);
01928 close(tmpfd);
01929 unlink(newtmp);
01930 }
01931 }
01932 #undef ENDL
01933 }
01934 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, struct ast_channel *chan, const char *category)
01935 {
01936 FILE *p=NULL;
01937 char tmp[80] = "/tmp/astmail-XXXXXX";
01938 char tmp2[256];
01939
01940 if (vmu && ast_strlen_zero(vmu->email)) {
01941 ast_log(LOG_WARNING, "E-mail address missing for mailbox [%s]. E-mail will not be sent.\n", vmu->mailbox);
01942 return(0);
01943 }
01944 if (!strcmp(format, "wav49"))
01945 format = "WAV";
01946 if (option_debug > 2)
01947 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));
01948
01949
01950 if ((p = vm_mkftemp(tmp)) == NULL) {
01951 ast_log(LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
01952 return -1;
01953 } else {
01954 make_email_file(p, srcemail, vmu, msgnum, context, mailbox, cidnum, cidname, attach, format, duration, attach_user_voicemail, chan, category, 0);
01955 fclose(p);
01956 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
01957 ast_safe_system(tmp2);
01958 if (option_debug > 2)
01959 ast_log(LOG_DEBUG, "Sent mail to %s with command '%s'\n", vmu->email, mailcmd);
01960 }
01961 return 0;
01962 }
01963
01964 static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char *mailbox, char *cidnum, char *cidname, int duration, struct ast_vm_user *vmu, const char *category)
01965 {
01966 char date[256];
01967 char host[MAXHOSTNAMELEN] = "";
01968 char who[256];
01969 char dur[PATH_MAX];
01970 char tmp[80] = "/tmp/astmail-XXXXXX";
01971 char tmp2[PATH_MAX];
01972 struct tm tm;
01973 FILE *p;
01974
01975 if ((p = vm_mkftemp(tmp)) == NULL) {
01976 ast_log(LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
01977 return -1;
01978 } else {
01979 gethostname(host, sizeof(host)-1);
01980 if (strchr(srcemail, '@'))
01981 ast_copy_string(who, srcemail, sizeof(who));
01982 else {
01983 snprintf(who, sizeof(who), "%s@%s", srcemail, host);
01984 }
01985 snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60);
01986 strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %z", vmu_tm(vmu, &tm));
01987 fprintf(p, "Date: %s\n", date);
01988
01989 if (*pagerfromstring) {
01990 struct ast_channel *ast;
01991 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
01992 char *passdata;
01993 int vmlen = strlen(fromstring)*3 + 200;
01994 if ((passdata = alloca(vmlen))) {
01995 memset(passdata, 0, vmlen);
01996 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
01997 pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
01998 fprintf(p, "From: %s <%s>\n", passdata, who);
01999 } else
02000 ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
02001 ast_channel_free(ast);
02002 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
02003 } else
02004 fprintf(p, "From: Asterisk PBX <%s>\n", who);
02005 fprintf(p, "To: %s\n", pager);
02006 if (pagersubject) {
02007 struct ast_channel *ast;
02008 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
02009 char *passdata;
02010 int vmlen = strlen(pagersubject) * 3 + 200;
02011 if ((passdata = alloca(vmlen))) {
02012 memset(passdata, 0, vmlen);
02013 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
02014 pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
02015 fprintf(p, "Subject: %s\n\n", passdata);
02016 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
02017 ast_channel_free(ast);
02018 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
02019 } else
02020 fprintf(p, "Subject: New VM\n\n");
02021 strftime(date, sizeof(date), "%A, %B %d, %Y at %r", &tm);
02022 if (pagerbody) {
02023 struct ast_channel *ast;
02024 if ((ast = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, 0))) {
02025 char *passdata;
02026 int vmlen = strlen(pagerbody)*3 + 200;
02027 if ((passdata = alloca(vmlen))) {
02028 memset(passdata, 0, vmlen);
02029 prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
02030 pbx_substitute_variables_helper(ast, pagerbody, passdata, vmlen);
02031 fprintf(p, "%s\n", passdata);
02032 } else ast_log(LOG_WARNING, "Cannot allocate workspace for variable substitution\n");
02033 ast_channel_free(ast);
02034 } else ast_log(LOG_WARNING, "Cannot allocate the channel for variables substitution\n");
02035 } else {
02036 fprintf(p, "New %s long msg in box %s\n"
02037 "from %s, on %s", dur, mailbox, (cidname ? cidname : (cidnum ? cidnum : "unknown")), date);
02038 }
02039 fclose(p);
02040 snprintf(tmp2, sizeof(tmp2), "( %s < %s ; rm -f %s ) &", mailcmd, tmp, tmp);
02041 ast_safe_system(tmp2);
02042 if (option_debug > 2)
02043 ast_log(LOG_DEBUG, "Sent page to %s with command '%s'\n", pager, mailcmd);
02044 }
02045 return 0;
02046 }
02047
02048 static int get_date(char *s, int len)
02049 {
02050 struct tm tm;
02051 time_t t;
02052 t = time(0);
02053 ast_localtime(&t, &tm, NULL);
02054 return strftime(s, len, "%a %b %e %r %Z %Y", &tm);
02055 }
02056
02057 static int invent_message(struct ast_channel *chan, char *context, char *ext, int busy, char *ecodes)
02058 {
02059 int res;
02060 char fn[PATH_MAX];
02061 char dest[PATH_MAX];
02062
02063 snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, context, ext);
02064
02065 if ((res = create_dirpath(dest, sizeof(dest), context, ext, "greet"))) {
02066 ast_log(LOG_WARNING, "Failed to make directory(%s)\n", fn);
02067 return -1;
02068 }
02069
02070 RETRIEVE(fn, -1);
02071 if (ast_fileexists(fn, NULL, NULL) > 0) {
02072 res = ast_stream_and_wait(chan, fn, chan->language, ecodes);
02073 if (res) {
02074 DISPOSE(fn, -1);
02075 return res;
02076 }
02077 } else {
02078
02079 DISPOSE(fn, -1);
02080 res = ast_stream_and_wait(chan, "vm-theperson", chan->language, ecodes);
02081 if (res)
02082 return res;
02083 res = ast_say_digit_str(chan, ext, ecodes, chan->language);
02084 if (res)
02085 return res;
02086 }
02087 res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", chan->language, ecodes);
02088 return res;
02089 }
02090
02091 static void free_user(struct ast_vm_user *vmu)
02092 {
02093 if (ast_test_flag(vmu, VM_ALLOCED))
02094 free(vmu);
02095 }
02096
02097 static void free_zone(struct vm_zone *z)
02098 {
02099 free(z);
02100 }
02101
02102 static const char *mbox(int id)
02103 {
02104 static const char *msgs[] = {
02105 "INBOX",
02106 "Old",
02107 "Work",
02108 "Family",
02109 "Friends",
02110 "Cust1",
02111 "Cust2",
02112 "Cust3",
02113 "Cust4",
02114 "Cust5",
02115 };
02116 return (id >= 0 && id < (sizeof(msgs)/sizeof(msgs[0]))) ? msgs[id] : "Unknown";
02117 }
02118 #ifdef IMAP_STORAGE
02119 static int folder_int(const char *folder)
02120 {
02121
02122 if (!folder)
02123 return 0;
02124 if(!strcasecmp(folder, "INBOX"))
02125 return 0;
02126 else if (!strcasecmp(folder, "Old"))
02127 return 1;
02128 else if (!strcasecmp(folder, "Work"))
02129 return 2;
02130 else if (!strcasecmp(folder, "Family"))
02131 return 3;
02132 else if (!strcasecmp(folder, "Friends"))
02133 return 4;
02134 else if (!strcasecmp(folder, "Cust1"))
02135 return 5;
02136 else if (!strcasecmp(folder, "Cust2"))
02137 return 6;
02138 else if (!strcasecmp(folder, "Cust3"))
02139 return 7;
02140 else if (!strcasecmp(folder, "Cust4"))
02141 return 8;
02142 else if (!strcasecmp(folder, "Cust5"))
02143 return 9;
02144 else
02145 return 0;
02146 }
02147 #endif
02148
02149 #ifdef ODBC_STORAGE
02150
02151 static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
02152 {
02153 int x = -1;
02154 int res;
02155 SQLHSTMT stmt;
02156 char sql[PATH_MAX];
02157 char rowdata[20];
02158 char tmp[PATH_MAX] = "";
02159 struct odbc_obj *obj;
02160 char *context;
02161 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
02162
02163 if (newmsgs)
02164 *newmsgs = 0;
02165 if (oldmsgs)
02166 *oldmsgs = 0;
02167
02168
02169 if (ast_strlen_zero(mailbox))
02170 return 0;
02171
02172 ast_copy_string(tmp, mailbox, sizeof(tmp));
02173
02174 context = strchr(tmp, '@');
02175 if (context) {
02176 *context = '\0';
02177 context++;
02178 } else
02179 context = "default";
02180
02181 obj = ast_odbc_request_obj(odbc_database, 0);
02182 if (obj) {
02183 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "INBOX");
02184 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
02185 if (!stmt) {
02186 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02187 ast_odbc_release_obj(obj);
02188 goto yuck;
02189 }
02190 res = SQLFetch(stmt);
02191 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02192 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02193 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02194 ast_odbc_release_obj(obj);
02195 goto yuck;
02196 }
02197 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02198 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02199 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02200 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02201 ast_odbc_release_obj(obj);
02202 goto yuck;
02203 }
02204 *newmsgs = atoi(rowdata);
02205 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02206
02207 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "Old");
02208 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
02209 if (!stmt) {
02210 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02211 ast_odbc_release_obj(obj);
02212 goto yuck;
02213 }
02214 res = SQLFetch(stmt);
02215 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02216 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02217 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02218 ast_odbc_release_obj(obj);
02219 goto yuck;
02220 }
02221 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02222 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02223 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02224 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02225 ast_odbc_release_obj(obj);
02226 goto yuck;
02227 }
02228 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02229 ast_odbc_release_obj(obj);
02230 *oldmsgs = atoi(rowdata);
02231 x = 0;
02232 } else
02233 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
02234
02235 yuck:
02236 return x;
02237 }
02238
02239 static int messagecount(const char *context, const char *mailbox, const char *folder)
02240 {
02241 struct odbc_obj *obj = NULL;
02242 int nummsgs = 0;
02243 int res;
02244 SQLHSTMT stmt = NULL;
02245 char sql[PATH_MAX];
02246 char rowdata[20];
02247 struct generic_prepare_struct gps = { .sql = sql, .argc = 0 };
02248 if (!folder)
02249 folder = "INBOX";
02250
02251 if (ast_strlen_zero(mailbox))
02252 return 0;
02253
02254 obj = ast_odbc_request_obj(odbc_database, 0);
02255 if (obj) {
02256 snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder);
02257 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps);
02258 if (!stmt) {
02259 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
02260 goto yuck;
02261 }
02262 res = SQLFetch(stmt);
02263 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02264 ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
02265 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02266 goto yuck;
02267 }
02268 res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
02269 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
02270 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
02271 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02272 goto yuck;
02273 }
02274 nummsgs = atoi(rowdata);
02275 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
02276 } else
02277 ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
02278
02279 yuck:
02280 if (obj)
02281 ast_odbc_release_obj(obj);
02282 return nummsgs;
02283 }
02284
02285 static int has_voicemail(const char *mailbox, const char *folder)
02286 {
02287 char tmp[256], *tmp2 = tmp, *mbox, *context;
02288 ast_copy_string(tmp, mailbox, sizeof(tmp));
02289 while ((context = mbox = strsep(&tmp2, ","))) {
02290 strsep(&context, "@");
02291 if (ast_strlen_zero(context))
02292 context = "default";
02293 if (messagecount(context, mbox, folder))
02294 return 1;
02295 }
02296 return 0;
02297 }
02298
02299 #elif defined(IMAP_STORAGE)
02300
02301 static int imap_store_file(char *dir, char *mailboxuser, char *mailboxcontext, int msgnum, struct ast_channel *chan, struct ast_vm_user *vmu, char *fmt, int duration, struct vm_state *vms)
02302 {
02303 char *myserveremail = serveremail;
02304 char fn[PATH_MAX];
02305 char mailbox[256];
02306 char *stringp;
02307 FILE *p=NULL;
02308 char tmp[80] = "/tmp/astmail-XXXXXX";
02309 long len;
02310 void *buf;
02311 STRING str;
02312
02313
02314 fmt = ast_strdupa(fmt);
02315 stringp = fmt;
02316 strsep(&stringp, "|");
02317
02318 if (!ast_strlen_zero(vmu->serveremail))
02319 myserveremail = vmu->serveremail;
02320
02321 make_file(fn, sizeof(fn), dir, msgnum);
02322
02323 if (ast_strlen_zero(vmu->email))
02324 ast_copy_string(vmu->email, vmu->imapuser, sizeof(vmu->email));
02325
02326 if (!strcmp(fmt, "wav49"))
02327 fmt = "WAV";
02328 if(option_debug > 2)
02329 ast_log(LOG_DEBUG, "Storing file '%s', format '%s'\n", fn, fmt);
02330
02331
02332 if ((p = vm_mkftemp(tmp)) == NULL) {
02333 ast_log(LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
02334 return -1;
02335 } else {
02336 make_email_file(p, myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), fn, fmt, duration, 1, chan, NULL, 1);
02337
02338 len = ftell(p);
02339 rewind(p);
02340 if((buf = ast_malloc(len+1)) == NIL) {
02341 ast_log(LOG_ERROR, "Can't allocate %ld bytes to read message\n", len+1);
02342 return -1;
02343 }
02344 fread(buf, len, 1, p);
02345 ((char *)buf)[len] = '\0';
02346 INIT(&str, mail_string, buf, len);
02347 init_mailstream(vms, 0);
02348 imap_mailbox_name(mailbox, vms, 0, 1);
02349 if(!mail_append(vms->mailstream, mailbox, &str))
02350 ast_log(LOG_ERROR, "Error while sending the message to %s\n", mailbox);
02351 fclose(p);
02352 unlink(tmp);
02353 ast_free(buf);
02354 if(option_debug > 2)
02355 ast_log(LOG_DEBUG, "%s stored\n", fn);
02356 }
02357 return 0;
02358
02359 }
02360
02361 static int messagecount(const char *context, const char *mailbox, const char *folder)
02362 {
02363 SEARCHPGM *pgm;
02364 SEARCHHEADER *hdr;
02365
02366 struct ast_vm_user *vmu, vmus;
02367 struct vm_state *vms_p;
02368 int ret = 0;
02369 int fold = folder_int(folder);
02370
02371 if (ast_strlen_zero(mailbox))
02372 return 0;
02373
02374
02375
02376 vmu = find_user(&vmus, context, mailbox);
02377 if (!vmu) {
02378 ast_log (LOG_ERROR,"Couldn't find mailbox %s in context %s\n",mailbox,context);
02379 return -1;
02380 } else {
02381
02382 if (vmu->imapuser[0] == '\0') {
02383 ast_log (LOG_WARNING,"IMAP user not set for mailbox %s\n",vmu->mailbox);
02384 return -1;
02385 }
02386 }
02387
02388
02389 vms_p = get_vm_state_by_imapuser(vmu->imapuser,1);
02390 if (!vms_p) {
02391 vms_p = get_vm_state_by_mailbox(mailbox,1);
02392 }
02393 if (vms_p) {
02394 if(option_debug > 2)
02395 ast_log (LOG_DEBUG,"Returning before search - user is logged in\n");
02396 if(fold == 0) {
02397 return vms_p->newmessages;
02398 }
02399 if(fold == 1) {
02400 return vms_p->oldmessages;
02401 }
02402 }
02403
02404
02405 vms_p = get_vm_state_by_imapuser(vmu->imapuser,0);
02406 if (!vms_p) {
02407 vms_p = get_vm_state_by_mailbox(mailbox,0);
02408 }
02409
02410 if (!vms_p) {
02411 if(option_debug > 2)
02412 ast_log (LOG_DEBUG,"Adding new vmstate for %s\n",vmu->imapuser);
02413 if (!(vms_p = ast_calloc(1, sizeof(*vms_p)))) {
02414 return -1;
02415 }
02416 ast_copy_string(vms_p->imapuser,vmu->imapuser, sizeof(vms_p->imapuser));
02417 ast_copy_string(vms_p->username, mailbox, sizeof(vms_p->username));
02418 vms_p->mailstream = NIL;
02419 if(option_debug > 2)
02420 ast_log (LOG_DEBUG,"Copied %s to %s\n",vmu->imapuser,vms_p->imapuser);
02421 vms_p->updated = 1;
02422
02423 ast_copy_string(vms_p->curbox, mbox(fold), sizeof(vms_p->curbox));
02424 init_vm_state(vms_p);
02425 vmstate_insert(vms_p);
02426 }
02427 ret = init_mailstream(vms_p, fold);
02428 if (!vms_p->mailstream) {
02429 ast_log (LOG_ERROR,"IMAP mailstream is NULL\n");
02430 return -1;
02431 }
02432 if (ret == 0) {
02433 pgm = mail_newsearchpgm ();
02434 hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", (char *)mailbox);
02435 pgm->header = hdr;
02436 if (fold != 1) {
02437 pgm->unseen = 1;
02438 pgm->seen = 0;
02439 }
02440
02441
02442
02443 else {
02444 pgm->unseen = 0;
02445 pgm->seen = 1;
02446 }
02447 pgm->undeleted = 1;
02448 pgm->deleted = 0;
02449
02450 vms_p->vmArrayIndex = 0;
02451 mail_search_full (vms_p->mailstream, NULL, pgm, NIL);
02452 if(fold == 0)
02453 vms_p->newmessages = vms_p->vmArrayIndex;
02454 if(fold == 1)
02455 vms_p->oldmessages = vms_p->vmArrayIndex;
02456
02457 mail_free_searchpgm(&pgm);
02458 vms_p->updated = 0;
02459 return vms_p->vmArrayIndex;
02460 } else {
02461 mail_ping(vms_p->mailstream);
02462 }
02463 return 0;
02464 }
02465 static int inboxcount(const char *mailbox_context, int *newmsgs, int *oldmsgs)
02466 {
02467 char tmp[PATH_MAX] = "";
02468 char *mailboxnc;
02469 char *context;
02470 char *mb;
02471 char *cur;
02472 if (newmsgs)
02473 *newmsgs = 0;
02474 if (oldmsgs)
02475 *oldmsgs = 0;
02476
02477 if(option_debug > 2)
02478 ast_log (LOG_DEBUG,"Mailbox is set to %s\n",mailbox_context);
02479
02480 if (ast_strlen_zero(mailbox_context))
02481 return 0;
02482
02483 ast_copy_string(tmp, mailbox_context, sizeof(tmp));
02484 context = strchr(tmp, '@');
02485 if (strchr(mailbox_context, ',')) {
02486 int tmpnew, tmpold;
02487 ast_copy_string(tmp, mailbox_context, sizeof(tmp));
02488 mb = tmp;
02489 while((cur = strsep(&mb, ", "))) {
02490 if (!ast_strlen_zero(cur)) {
02491 if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
02492 return -1;
02493 else {
02494 if (newmsgs)
02495 *newmsgs += tmpnew;
02496 if (oldmsgs)
02497 *oldmsgs += tmpold;
02498 }
02499 }
02500 }
02501 return 0;
02502 }
02503 if (context) {
02504 *context = '\0';
02505 mailboxnc = tmp;
02506 context++;
02507 } else {
02508 context = "default";
02509 mailboxnc = (char *)mailbox_context;
02510 }
02511 if (newmsgs) {
02512 if((*newmsgs = messagecount(context, mailboxnc, "INBOX")) < 0)
02513 return -1;
02514 }
02515 if (oldmsgs) {
02516 if((*oldmsgs = messagecount(context, mailboxnc, "Old")) < 0)
02517 return -1;
02518 }
02519 return 0;
02520 }
02521
02522
02523 static int has_voicemail(const char *mailbox, const char *folder)
02524 {
02525 char tmp[256], *tmp2, *mbox, *context;
02526 ast_copy_string(tmp, mailbox, sizeof(tmp));
02527 tmp2 = tmp;
02528 if(strchr(tmp2, ',')) {
02529 while((mbox = strsep(&tmp2, ","))) {
02530 if(!ast_strlen_zero(mbox)) {
02531 if (has_voicemail(mbox, folder))
02532 return 1;
02533 }
02534 }
02535 }
02536 if ((context= strchr(tmp, '@')))
02537 *context++ = '\0';
02538 else
02539 context = "default";
02540 return messagecount(context, tmp, folder) ? 1 : 0;
02541 }
02542
02543 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, char *dir)
02544 {
02545 char dest[256];
02546 struct vm_state *sendvms = NULL, *destvms = NULL;
02547 char messagestring[10];
02548 if(!(sendvms = get_vm_state_by_imapuser(vmu->imapuser, 2)))
02549 {
02550 ast_log(LOG_ERROR, "Couldn't get vm_state for originator's mailbox!!\n");
02551 return -1;
02552 }
02553 if(!(destvms = get_vm_state_by_imapuser(recip->imapuser, 2)))
02554 {
02555 ast_log(LOG_ERROR, "Couldn't get vm_state for destination mailbox!\n");
02556 return -1;
02557 }
02558 imap_mailbox_name(dest, destvms, imbox, 1);
02559 snprintf(messagestring, sizeof(messagestring), "%ld", sendvms->msgArray[msgnum]);
02560 if((mail_copy(sendvms->mailstream, messagestring, dest) == T))
02561 return 0;
02562 ast_log(LOG_WARNING, "Unable to copy message from mailbox %s to mailbox %s\n", vmu->mailbox, recip->mailbox);
02563 return -1;
02564 }
02565
02566 #endif
02567 #ifndef IMAP_STORAGE
02568
02569 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, char *dir)
02570 {
02571 char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX];
02572 const char *frombox = mbox(imbox);
02573 int recipmsgnum;
02574
02575 ast_log(LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context);
02576
02577 create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, "INBOX");
02578
02579 if (!dir)
02580 make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox);
02581 else
02582 ast_copy_string(fromdir, dir, sizeof(fromdir));
02583
02584 make_file(frompath, sizeof(frompath), fromdir, msgnum);
02585
02586 if (vm_lock_path(todir))
02587 return ERROR_LOCK_PATH;
02588
02589 recipmsgnum = 0;
02590 do {
02591 make_file(topath, sizeof(topath), todir, recipmsgnum);
02592 if (!EXISTS(todir, recipmsgnum, topath, chan->language))
02593 break;
02594 recipmsgnum++;
02595 } while (recipmsgnum < recip->maxmsg);
02596 if (recipmsgnum < recip->maxmsg) {
02597 COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath);
02598 } else {
02599 ast_log(LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context);
02600 }
02601 ast_unlock_path(todir);
02602 notify_new_message(chan, recip, recipmsgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
02603
02604 return 0;
02605 }
02606 #endif
02607 #if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE))
02608 static int messagecount(const char *context, const char *mailbox, const char *folder)
02609 {
02610 return __has_voicemail(context, mailbox, folder, 0);
02611 }
02612
02613
02614 static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit)
02615 {
02616 DIR *dir;
02617 struct dirent *de;
02618 char fn[256];
02619 int ret = 0;
02620 if (!folder)
02621 folder = "INBOX";
02622
02623 if (ast_strlen_zero(mailbox))
02624 return 0;
02625 if (!context)
02626 context = "default";
02627 snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);
02628 dir = opendir(fn);
02629 if (!dir)
02630 return 0;
02631 while ((de = readdir(dir))) {
02632 if (!strncasecmp(de->d_name, "msg", 3)) {
02633 if (shortcircuit) {
02634 ret = 1;
02635 break;
02636 } else if (!strncasecmp(de->d_name + 8, "txt", 3))
02637 ret++;
02638 }
02639 }
02640 closedir(dir);
02641 return ret;
02642 }
02643
02644
02645 static int has_voicemail(const char *mailbox, const char *folder)
02646 {
02647 char tmp[256], *tmp2 = tmp, *mbox, *context;
02648 ast_copy_string(tmp, mailbox, sizeof(tmp));
02649 while ((mbox = strsep(&tmp2, ","))) {
02650 if ((context = strchr(mbox, '@')))
02651 *context++ = '\0';
02652 else
02653 context = "default";
02654 if (__has_voicemail(context, mbox, folder, 1))
02655 return 1;
02656 }
02657 return 0;
02658 }
02659
02660
02661 static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
02662 {
02663 char tmp[256];
02664 char *context;
02665
02666 if (newmsgs)
02667 *newmsgs = 0;
02668 if (oldmsgs)
02669 *oldmsgs = 0;
02670
02671 if (ast_strlen_zero(mailbox))
02672 return 0;
02673 if (strchr(mailbox, ',')) {
02674 int tmpnew, tmpold;
02675 char *mb, *cur;
02676
02677 ast_copy_string(tmp, mailbox, sizeof(tmp));
02678 mb = tmp;
02679 while ((cur = strsep(&mb, ", "))) {
02680 if (!ast_strlen_zero(cur)) {
02681 if (inboxcount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
02682 return -1;
02683 else {
02684 if (newmsgs)
02685 *newmsgs += tmpnew;
02686 if (oldmsgs)
02687 *oldmsgs += tmpold;
02688 }
02689 }
02690 }
02691 return 0;
02692 }
02693 ast_copy_string(tmp, mailbox, sizeof(tmp));
02694 context = strchr(tmp, '@');
02695 if (context) {
02696 *context = '\0';
02697 context++;
02698 } else
02699 context = "default";
02700 if (newmsgs)
02701 *newmsgs = __has_voicemail(context, tmp, "INBOX", 0);
02702 if (oldmsgs)
02703 *oldmsgs = __has_voicemail(context, tmp, "Old", 0);
02704 return 0;
02705 }
02706
02707 #endif
02708
02709 static void run_externnotify(char *context, char *extension)
02710 {
02711 char arguments[255];
02712 char ext_context[256] = "";
02713 int newvoicemails = 0, oldvoicemails = 0;
02714 struct ast_smdi_mwi_message *mwi_msg;
02715
02716 if (!ast_strlen_zero(context))
02717 snprintf(ext_context, sizeof(ext_context), "%s@%s", extension, context);
02718 else
02719 ast_copy_string(ext_context, extension, sizeof(ext_context));
02720
02721 if (!strcasecmp(externnotify, "smdi")) {
02722 if (ast_app_has_voicemail(ext_context, NULL))
02723 ast_smdi_mwi_set(smdi_iface, extension);
02724 else
02725 ast_smdi_mwi_unset(smdi_iface, extension);
02726
02727 if ((mwi_msg = ast_smdi_mwi_message_wait(smdi_iface, SMDI_MWI_WAIT_TIMEOUT))) {
02728 ast_log(LOG_ERROR, "Error executing SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
02729 if (!strncmp(mwi_msg->cause, "INV", 3))
02730 ast_log(LOG_ERROR, "Invalid MWI extension: %s\n", mwi_msg->fwd_st);
02731 else if (!strncmp(mwi_msg->cause, "BLK", 3))
02732 ast_log(LOG_WARNING, "MWI light was already on or off for %s\n", mwi_msg->fwd_st);
02733 ast_log(LOG_WARNING, "The switch reported '%s'\n", mwi_msg->cause);
02734 ASTOBJ_UNREF(mwi_msg, ast_smdi_mwi_message_destroy);
02735 } else {
02736 if (option_debug)
02737 ast_log(LOG_DEBUG, "Successfully executed SMDI MWI change for %s on %s\n", extension, smdi_iface->name);
02738 }
02739 } else if (!ast_strlen_zero(externnotify)) {
02740 if (inboxcount(ext_context, &newvoicemails, &oldvoicemails)) {
02741 ast_log(LOG_ERROR, "Problem in calculating number of voicemail messages available for extension %s\n", extension);
02742 } else {
02743 snprintf(arguments, sizeof(arguments), "%s %s %s %d&", externnotify, context, extension, newvoicemails);
02744 if (option_debug)
02745 ast_log(LOG_DEBUG, "Executing %s\n", arguments);
02746 ast_safe_system(arguments);
02747 }
02748 }
02749 }
02750
02751 struct leave_vm_options {
02752 unsigned int flags;
02753 signed char record_gain;
02754 };
02755
02756 static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_options *options)
02757 {
02758 #ifdef IMAP_STORAGE
02759 int newmsgs, oldmsgs;
02760 struct vm_state *vms = NULL;
02761 #endif
02762 char txtfile[PATH_MAX], tmptxtfile[PATH_MAX];
02763 char callerid[256];
02764 FILE *txt;
02765 char date[256];
02766 int txtdes;
02767 int res = 0;
02768 int msgnum;
02769 int duration = 0;
02770 int ausemacro = 0;
02771 int ousemacro = 0;
02772 int ouseexten = 0;
02773 char dir[PATH_MAX], tmpdir[PATH_MAX];
02774 char dest[PATH_MAX];
02775 char fn[PATH_MAX];
02776 char prefile[PATH_MAX] = "";
02777 char tempfile[PATH_MAX] = "";
02778 char ext_context[256] = "";
02779 char fmt[80];
02780 char *context;
02781 char ecodes[16] = "#";
02782 char tmp[1024] = "", *tmpptr;
02783 struct ast_vm_user *vmu;
02784 struct ast_vm_user svm;
02785 const char *category = NULL;
02786
02787 ast_copy_string(tmp, ext, sizeof(tmp));
02788 ext = tmp;
02789 context = strchr(tmp, '@');
02790 if (context) {
02791 *context++ = '\0';
02792 tmpptr = strchr(context, '&');
02793 } else {
02794 tmpptr = strchr(ext, '&');
02795 }
02796
02797 if (tmpptr)
02798 *tmpptr++ = '\0';
02799
02800 category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
02801
02802 if(option_debug > 2)
02803 ast_log(LOG_DEBUG, "Before find_user\n");
02804 if (!(vmu = find_user(&svm, context, ext))) {
02805 ast_log(LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext);
02806 if (ast_test_flag(options, OPT_PRIORITY_JUMP) || ast_opt_priority_jumping)
02807 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
02808 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02809 return res;
02810 }
02811
02812 if (strcmp(vmu->context, "default"))
02813 snprintf(ext_context, sizeof(ext_context), "%s@%s", ext, vmu->context);
02814 else
02815 ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context));
02816 if (ast_test_flag(options, OPT_BUSY_GREETING)) {
02817 res = create_dirpath(dest, sizeof(dest), vmu->context, ext, "busy");
02818 snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, ext);
02819 } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) {
02820 res = create_dirpath(dest, sizeof(dest), vmu->context, ext, "unavail");
02821 snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext);
02822 }
02823 snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext);
02824 if ((res = create_dirpath(dest, sizeof(dest), vmu->context, ext, "temp"))) {
02825 ast_log(LOG_WARNING, "Failed to make directory (%s)\n", tempfile);
02826 return -1;
02827 }
02828 RETRIEVE(tempfile, -1);
02829 if (ast_fileexists(tempfile, NULL, NULL) > 0)
02830 ast_copy_string(prefile, tempfile, sizeof(prefile));
02831 DISPOSE(tempfile, -1);
02832
02833 create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX");
02834 create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp");
02835
02836
02837 if (ast_test_flag(vmu, VM_OPERATOR)) {
02838 if (!ast_strlen_zero(vmu->exit)) {
02839 if (ast_exists_extension(chan, vmu->exit, "o", 1, chan->cid.cid_num)) {
02840 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02841 ouseexten = 1;
02842 }
02843 } else if (ast_exists_extension(chan, chan->context, "o", 1, chan->cid.cid_num)) {
02844 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02845 ouseexten = 1;
02846 }
02847 else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "o", 1, chan->cid.cid_num)) {
02848 strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1);
02849 ousemacro = 1;
02850 }
02851 }
02852
02853 if (!ast_strlen_zero(vmu->exit)) {
02854 if (ast_exists_extension(chan, vmu->exit, "a", 1, chan->cid.cid_num))
02855 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02856 } else if (ast_exists_extension(chan, chan->context, "a", 1, chan->cid.cid_num))
02857 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02858 else if (!ast_strlen_zero(chan->macrocontext) && ast_exists_extension(chan, chan->macrocontext, "a", 1, chan->cid.cid_num)) {
02859 strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1);
02860 ausemacro = 1;
02861 }
02862
02863
02864 if (!ast_strlen_zero(prefile)) {
02865 #ifdef ODBC_STORAGE
02866 int success =
02867 #endif
02868 RETRIEVE(prefile, -1);
02869 if (ast_fileexists(prefile, NULL, NULL) > 0) {
02870 if (ast_streamfile(chan, prefile, chan->language) > -1)
02871 res = ast_waitstream(chan, ecodes);
02872 #ifdef ODBC_STORAGE
02873 if (success == -1) {
02874
02875 if (option_debug)
02876 ast_log(LOG_DEBUG, "Greeting not retrieved from database, but found in file storage. Inserting into database\n");
02877 store_file(prefile, vmu->mailbox, vmu->context, -1);
02878 }
02879 #endif
02880 } else {
02881 if (option_debug)
02882 ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
02883 res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes);
02884 }
02885 DISPOSE(prefile, -1);
02886 if (res < 0) {
02887 if (option_debug)
02888 ast_log(LOG_DEBUG, "Hang up during prefile playback\n");
02889 free_user(vmu);
02890 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02891 return -1;
02892 }
02893 }
02894 if (res == '#') {
02895
02896 ast_set_flag(options, OPT_SILENT);
02897 res = 0;
02898 }
02899 if (!res && !ast_test_flag(options, OPT_SILENT)) {
02900 res = ast_stream_and_wait(chan, INTRO, chan->language, ecodes);
02901 if (res == '#') {
02902 ast_set_flag(options, OPT_SILENT);
02903 res = 0;
02904 }
02905 }
02906 if (res > 0)
02907 ast_stopstream(chan);
02908
02909
02910 if (res == '*') {
02911 chan->exten[0] = 'a';
02912 chan->exten[1] = '\0';
02913 if (!ast_strlen_zero(vmu->exit)) {
02914 ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02915 } else if (ausemacro && !ast_strlen_zero(chan->macrocontext)) {
02916 ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02917 }
02918 chan->priority = 0;
02919 free_user(vmu);
02920 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
02921 return 0;
02922 }
02923
02924
02925 if (res == '0') {
02926 transfer:
02927 if (ouseexten || ousemacro) {
02928 chan->exten[0] = 'o';
02929 chan->exten[1] = '\0';
02930 if (!ast_strlen_zero(vmu->exit)) {
02931 ast_copy_string(chan->context, vmu->exit, sizeof(chan->context));
02932 } else if (ousemacro && !ast_strlen_zero(chan->macrocontext)) {
02933 ast_copy_string(chan->context, chan->macrocontext, sizeof(chan->context));
02934 }
02935 ast_play_and_wait(chan, "transfer");
02936 chan->priority = 0;
02937 free_user(vmu);
02938 pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT");
02939 }
02940 return 0;
02941 }
02942 if (res < 0) {
02943 free_user(vmu);
02944 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
02945 return -1;
02946 }
02947
02948 ast_copy_string(fmt, vmfmts, sizeof(fmt));
02949 if (!ast_strlen_zero(fmt)) {
02950 msgnum = 0;
02951
02952 #ifdef IMAP_STORAGE
02953
02954
02955 res = inboxcount(ext_context, &newmsgs, &oldmsgs);
02956 if(res < 0) {
02957 ast_log(LOG_NOTICE,"Can not leave voicemail, unable to count messages\n");
02958 return -1;
02959 }
02960 if(!(vms = get_vm_state_by_mailbox(ext,0))) {
02961
02962
02963 if (!(vms = ast_calloc(1, sizeof(*vms)))) {
02964 ast_log(LOG_ERROR, "Couldn't allocate necessary space\n");
02965 return -1;
02966 }
02967 ast_copy_string(vms->imapuser, vmu->imapuser, sizeof(vms->imapuser));
02968 ast_copy_string(vms->username, ext, sizeof(vms->username));
02969 vms->mailstream = NIL;
02970 if (option_debug > 2)
02971 ast_log(LOG_DEBUG, "Copied %s to %s\n", vmu->imapuser, vms->imapuser);
02972 vms->updated=1;
02973 ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
02974 init_vm_state(vms);
02975 vmstate_insert(vms);
02976 vms = get_vm_state_by_mailbox(ext,0);
02977 }
02978 vms->newmessages++;
02979
02980 msgnum = newmsgs + oldmsgs;
02981 if (option_debug > 2)
02982 ast_log(LOG_DEBUG, "Messagecount set to %d\n",msgnum);
02983 snprintf(fn, sizeof(fn), "%s/imap/msg%s%04d", VM_SPOOL_DIR, vmu->mailbox, msgnum);
02984
02985 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
02986
02987
02988 if (vms->quota_limit && vms->quota_usage >= vms->quota_limit) {
02989 if(option_debug)
02990 ast_log(LOG_DEBUG, "*** QUOTA EXCEEDED!! %u >= %u\n", vms->quota_usage, vms->quota_limit);
02991 ast_play_and_wait(chan, "vm-mailboxfull");
02992 return -1;
02993 }
02994
02995 if (option_debug > 2)
02996 ast_log(LOG_DEBUG, "Messagecount set to %d\n",msgnum);
02997 #else
02998 if (count_messages(vmu, dir) >= vmu->maxmsg) {
02999 res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
03000 if (!res)
03001 res = ast_waitstream(chan, "");
03002 ast_log(LOG_WARNING, "No more messages possible\n");
03003 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
03004 goto leave_vm_out;
03005 }
03006
03007 #endif
03008 snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir);
03009 txtdes = mkstemp(tmptxtfile);
03010 chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask);
03011 if (txtdes < 0) {
03012 res = ast_streamfile(chan, "vm-mailboxfull", chan->language);
03013 if (!res)
03014 res = ast_waitstream(chan, "");
03015 ast_log(LOG_ERROR, "Unable to create message file: %s\n", strerror(errno));
03016 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
03017 goto leave_vm_out;
03018 }
03019
03020
03021 if (res >= 0) {
03022
03023 res = ast_stream_and_wait(chan, "beep", chan->language, "");
03024 }
03025
03026
03027 txt = fdopen(txtdes, "w+");
03028 if (txt) {
03029 get_date(date, sizeof(date));
03030 fprintf(txt,
03031 ";\n"
03032 "; Message Information file\n"
03033 ";\n"
03034 "[message]\n"
03035 "origmailbox=%s\n"
03036 "context=%s\n"
03037 "macrocontext=%s\n"
03038 "exten=%s\n"
03039 "priority=%d\n"
03040 "callerchan=%s\n"
03041 "callerid=%s\n"
03042 "origdate=%s\n"
03043 "origtime=%ld\n"
03044 "category=%s\n",
03045 ext,
03046 chan->context,
03047 chan->macrocontext,
03048 chan->exten,
03049 chan->priority,
03050 chan->name,
03051 ast_callerid_merge(callerid, sizeof(callerid), S_OR(chan->cid.cid_name, NULL), S_OR(chan->cid.cid_num, NULL), "Unknown"),
03052 date, (long)time(NULL),
03053 category ? category : "");
03054 } else
03055 ast_log(LOG_WARNING, "Error opening text file for output\n");
03056 #ifdef IMAP_STORAGE
03057 res = play_record_review(chan, NULL, tmptxtfile, vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain, vms);
03058 #else
03059 res = play_record_review(chan, NULL, tmptxtfile, vmmaxmessage, fmt, 1, vmu, &duration, NULL, options->record_gain, NULL);
03060 #endif
03061
03062 if (txt) {
03063 if (duration < vmminmessage) {
03064 if (option_verbose > 2)
03065 ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminmessage);
03066 ast_filedelete(tmptxtfile, NULL);
03067 unlink(tmptxtfile);
03068 } else {
03069 fprintf(txt, "duration=%d\n", duration);
03070 fclose(txt);
03071 if (vm_lock_path(dir)) {
03072 ast_log(LOG_ERROR, "Couldn't lock directory %s. Voicemail will be lost.\n", dir);
03073
03074 ast_filedelete(tmptxtfile, NULL);
03075 unlink(tmptxtfile);
03076 } else if (ast_fileexists(tmptxtfile, NULL, NULL) <= 0) {
03077 if (option_debug)
03078 ast_log(LOG_DEBUG, "The recorded media file is gone, so we should remove the .txt file too!\n");
03079 unlink(tmptxtfile);
03080 ast_unlock_path(dir);
03081 } else {
03082 for (;;) {
03083 make_file(fn, sizeof(fn), dir, msgnum);
03084 if (!EXISTS(dir, msgnum, fn, NULL))
03085 break;
03086 msgnum++;
03087 }
03088
03089
03090 #ifndef IMAP_STORAGE
03091 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", fn);
03092 #else
03093 pbx_builtin_setvar_helper(chan, "VM_MESSAGEFILE", "IMAP_STORAGE");
03094 #endif
03095
03096 snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
03097 ast_filerename(tmptxtfile, fn, NULL);
03098 rename(tmptxtfile, txtfile);
03099
03100 ast_unlock_path(dir);
03101
03102
03103
03104 if (ast_fileexists(fn, NULL, NULL) > 0) {
03105 STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms);
03106 }
03107
03108
03109 while (tmpptr) {
03110 struct ast_vm_user recipu, *recip;
03111 char *exten, *context;
03112
03113 exten = strsep(&tmpptr, "&");
03114 context = strchr(exten, '@');
03115 if (context) {
03116 *context = '\0';
03117 context++;
03118 }
03119 if ((recip = find_user(&recipu, context, exten))) {
03120 copy_message(chan, vmu, 0, msgnum, duration, recip, fmt, dir);
03121 free_user(recip);
03122 }
03123 }
03124
03125 if (ast_fileexists(fn, NULL, NULL)) {
03126 notify_new_message(chan, vmu, msgnum, duration, fmt, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL));
03127 DISPOSE(dir, msgnum);
03128 }
03129 }
03130 }
03131 }
03132 if (res == '0') {
03133 goto transfer;
03134 } else if (res > 0)
03135 res = 0;
03136
03137 if (duration < vmminmessage)
03138
03139 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
03140 else
03141 pbx_builtin_setvar_helper(chan, "VMSTATUS", "SUCCESS");
03142 } else
03143 ast_log(LOG_WARNING, "No format for saving voicemail?\n");
03144 leave_vm_out:
03145 free_user(vmu);
03146
03147 return res;
03148 }
03149
03150 #ifndef IMAP_STORAGE
03151 static int resequence_mailbox(struct ast_vm_user *vmu, char *dir)
03152 {
03153
03154
03155 int x,dest;
03156 char sfn[PATH_MAX];
03157 char dfn[PATH_MAX];
03158
03159 if (vm_lock_path(dir))
03160 return ERROR_LOCK_PATH;
03161
03162 for (x = 0, dest = 0; x < vmu->maxmsg; x++) {
03163 make_file(sfn, sizeof(sfn), dir, x);
03164 if (EXISTS(dir, x, sfn, NULL)) {
03165
03166 if (x != dest) {
03167 make_file(dfn, sizeof(dfn), dir, dest);
03168 RENAME(dir, x, vmu->mailbox, vmu->context, dir, dest, sfn, dfn);
03169 }
03170
03171 dest++;
03172 }
03173 }
03174 ast_unlock_path(dir);
03175
03176 return 0;
03177 }
03178 #endif
03179
03180 static int say_and_wait(struct ast_channel *chan, int num, const char *language)
03181 {
03182 int d;
03183 d = ast_say_number(chan, num, AST_DIGIT_ANY, language, (char *) NULL);
03184 return d;
03185 }
03186
03187 static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg, int box)
03188 {
03189 #ifdef IMAP_STORAGE
03190
03191
03192 char dbox[256];
03193 long res;
03194 char sequence[10];
03195
03196
03197 if (box == 1) return 10;
03198
03199 sprintf(sequence,"%ld",vms->msgArray[msg]);
03200 imap_mailbox_name(dbox, vms, box, 1);
03201 if(option_debug > 2)
03202 ast_log(LOG_DEBUG, "Copying sequence %s to mailbox %s\n",sequence,dbox);
03203 res = mail_copy(vms->mailstream,sequence,dbox);
03204 if (res == 1) return 0;
03205 return 1;
03206 #else
03207 char *dir = vms->curdir;
03208 char *username = vms->username;
03209 char *context = vmu->context;
03210 char sfn[PATH_MAX];
03211 char dfn[PATH_MAX];
03212 char ddir[PATH_MAX];
03213 const char *dbox = mbox(box);
03214 int x;
03215 make_file(sfn, sizeof(sfn), dir, msg);
03216 create_dirpath(ddir, sizeof(ddir), context, username, dbox);
03217
03218 if (vm_lock_path(ddir))
03219 return ERROR_LOCK_PATH;
03220
03221 for (x = 0; x < vmu->maxmsg; x++) {
03222 make_file(dfn, sizeof(dfn), ddir, x);
03223 if (!EXISTS(ddir, x, dfn, NULL))
03224 break;
03225 }
03226 if (x >= vmu->maxmsg) {
03227 ast_unlock_path(ddir);
03228 return -1;
03229 }
03230 if (strcmp(sfn, dfn)) {
03231 COPY(dir, msg, ddir, x, username, context, sfn, dfn);
03232 }
03233 ast_unlock_path(ddir);
03234 #endif
03235 return 0;
03236 }
03237
03238 static int adsi_logo(unsigned char *buf)
03239 {
03240 int bytes = 0;
03241 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, "Comedian Mail", "");
03242 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, "(C)2002-2006 Digium, Inc.", "");
03243 return bytes;
03244 }
03245
03246 static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
03247 {
03248 unsigned char buf[256];
03249 int bytes=0;
03250 int x;
03251 char num[5];
03252
03253 *useadsi = 0;
03254 bytes += ast_adsi_data_mode(buf + bytes);
03255 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03256
03257 bytes = 0;
03258 bytes += adsi_logo(buf);
03259 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
03260 #ifdef DISPLAY
03261 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .", "");
03262 #endif
03263 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03264 bytes += ast_adsi_data_mode(buf + bytes);
03265 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03266
03267 if (ast_adsi_begin_download(chan, addesc, adsifdn, adsisec, adsiver)) {
03268 bytes = 0;
03269 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Cancelled.", "");
03270 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
03271 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03272 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03273 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03274 return 0;
03275 }
03276
03277 #ifdef DISPLAY
03278
03279 bytes = 0;
03280 bytes += ast_adsi_logo(buf);
03281 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Downloading Scripts", "");
03282 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ..", "");
03283 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03284 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03285 #endif
03286 bytes = 0;
03287 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
03288 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
03289 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
03290 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
03291 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
03292 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
03293 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
03294
03295 #ifdef DISPLAY
03296
03297 bytes = 0;
03298 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ...", "");
03299 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03300
03301 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03302 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03303 #endif
03304
03305 bytes = 0;
03306
03307 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 6, "Previous", "Prev", "4", 1);
03308 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 8, "Repeat", "Repeat", "5", 1);
03309 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 7, "Delete", "Delete", "7", 1);
03310 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 9, "Next", "Next", "6", 1);
03311 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 10, "Save", "Save", "9", 1);
03312 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 11, "Undelete", "Restore", "7", 1);
03313 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
03314
03315 #ifdef DISPLAY
03316
03317 bytes = 0;
03318 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " ....", "");
03319 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03320 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03321 #endif
03322
03323 bytes = 0;
03324 for (x=0;x<5;x++) {
03325 snprintf(num, sizeof(num), "%d", x);
03326 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + x, mbox(x), mbox(x), num, 1);
03327 }
03328 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 12 + 5, "Cancel", "Cancel", "#", 1);
03329 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
03330
03331 #ifdef DISPLAY
03332
03333 bytes = 0;
03334 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, " .....", "");
03335 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03336 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03337 #endif
03338
03339 if (ast_adsi_end_download(chan)) {
03340 bytes = 0;
03341 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Download Unsuccessful.", "");
03342 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "ADSI Unavailable", "");
03343 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03344 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03345 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03346 return 0;
03347 }
03348 bytes = 0;
03349 bytes += ast_adsi_download_disconnect(buf + bytes);
03350 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03351 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
03352
03353 if (option_debug)
03354 ast_log(LOG_DEBUG, "Done downloading scripts...\n");
03355
03356 #ifdef DISPLAY
03357
03358 bytes = 0;
03359 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ......", "");
03360 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03361 #endif
03362 if (option_debug)
03363 ast_log(LOG_DEBUG, "Restarting session...\n");
03364
03365 bytes = 0;
03366
03367 if (ast_adsi_load_session(chan, adsifdn, adsiver, 1) == 1) {
03368 *useadsi = 1;
03369 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Scripts Loaded!", "");
03370 } else
03371 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Load Failed!", "");
03372
03373 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03374 return 0;
03375 }
03376
03377 static void adsi_begin(struct ast_channel *chan, int *useadsi)
03378 {
03379 int x;
03380 if (!ast_adsi_available(chan))
03381 return;
03382 x = ast_adsi_load_session(chan, adsifdn, adsiver, 1);
03383 if (x < 0)
03384 return;
03385 if (!x) {
03386 if (adsi_load_vmail(chan, useadsi)) {
03387 ast_log(LOG_WARNING, "Unable to upload voicemail scripts\n");
03388 return;
03389 }
03390 } else
03391 *useadsi = 1;
03392 }
03393
03394 static void adsi_login(struct ast_channel *chan)
03395 {
03396 unsigned char buf[256];
03397 int bytes=0;
03398 unsigned char keys[8];
03399 int x;
03400 if (!ast_adsi_available(chan))
03401 return;
03402
03403 for (x=0;x<8;x++)
03404 keys[x] = 0;
03405
03406 keys[3] = ADSI_KEY_APPS + 3;
03407
03408 bytes += adsi_logo(buf + bytes);
03409 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, " ", "");
03410 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, " ", "");
03411 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03412 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Mailbox: ******", "");
03413 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 1, 1, ADSI_JUST_LEFT);
03414 bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Enter", "Enter", "#", 1);
03415 bytes += ast_adsi_set_keys(buf + bytes, keys);
03416 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03417 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03418 }
03419
03420 static void adsi_password(struct ast_channel *chan)
03421 {
03422 unsigned char buf[256];
03423 int bytes=0;
03424 unsigned char keys[8];
03425 int x;
03426 if (!ast_adsi_available(chan))
03427 return;
03428
03429 for (x=0;x<8;x++)
03430 keys[x] = 0;
03431
03432 keys[3] = ADSI_KEY_APPS + 3;
03433
03434 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03435 bytes += ast_adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
03436 bytes += ast_adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
03437 bytes += ast_adsi_set_keys(buf + bytes, keys);
03438 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03439 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03440 }
03441
03442 static void adsi_folders(struct ast_channel *chan, int start, char *label)
03443 {
03444 unsigned char buf[256];
03445 int bytes=0;
03446 unsigned char keys[8];
03447 int x,y;
03448
03449 if (!ast_adsi_available(chan))
03450 return;
03451
03452 for (x=0;x<5;x++) {
03453 y = ADSI_KEY_APPS + 12 + start + x;
03454 if (y > ADSI_KEY_APPS + 12 + 4)
03455 y = 0;
03456 keys[x] = ADSI_KEY_SKT | y;
03457 }
03458 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 17);
03459 keys[6] = 0;
03460 keys[7] = 0;
03461
03462 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_CENT, 0, label, "");
03463 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
03464 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03465 bytes += ast_adsi_set_keys(buf + bytes, keys);
03466 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03467
03468 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03469 }
03470
03471 static void adsi_message(struct ast_channel *chan, struct vm_state *vms)
03472 {
03473 int bytes=0;
03474 unsigned char buf[256];
03475 char buf1[256], buf2[256];
03476 char fn2[PATH_MAX];
03477
03478 char cid[256]="";
03479 char *val;
03480 char *name, *num;
03481 char datetime[21]="";
03482 FILE *f;
03483
03484 unsigned char keys[8];
03485
03486 int x;
03487
03488 if (!ast_adsi_available(chan))
03489 return;
03490
03491
03492 snprintf(fn2, sizeof(fn2), "%s.txt", vms->fn);
03493 f = fopen(fn2, "r");
03494 if (f) {
03495 while (!feof(f)) {
03496 fgets((char *)buf, sizeof(buf), f);
03497 if (!feof(f)) {
03498 char *stringp=NULL;
03499 stringp = (char *)buf;
03500 strsep(&stringp, "=");
03501 val = strsep(&stringp, "=");
03502 if (!ast_strlen_zero(val)) {
03503 if (!strcmp((char *)buf, "callerid"))
03504 ast_copy_string(cid, val, sizeof(cid));
03505 if (!strcmp((char *)buf, "origdate"))
03506 ast_copy_string(datetime, val, sizeof(datetime));
03507 }
03508 }
03509 }
03510 fclose(f);
03511 }
03512
03513 for (x=0;x<5;x++)
03514 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
03515 keys[6] = 0x0;
03516 keys[7] = 0x0;
03517
03518 if (!vms->curmsg) {
03519
03520 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03521 }
03522 if (vms->curmsg >= vms->lastmsg) {
03523
03524 if (vms->curmsg) {
03525
03526 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03527 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03528
03529 } else {
03530
03531 keys[3] = 1;
03532 }
03533 }
03534
03535 if (!ast_strlen_zero(cid)) {
03536 ast_callerid_parse(cid, &name, &num);
03537 if (!name)
03538 name = num;
03539 } else
03540 name = "Unknown Caller";
03541
03542
03543
03544 if (vms->deleted[vms->curmsg])
03545 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
03546
03547
03548 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
03549 snprintf(buf1, sizeof(buf1), "%s%s", vms->curbox,
03550 strcasecmp(vms->curbox, "INBOX") ? " Messages" : "");
03551 snprintf(buf2, sizeof(buf2), "Message %d of %d", vms->curmsg + 1, vms->lastmsg + 1);
03552
03553 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03554 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03555 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, name, "");
03556 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
03557 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03558 bytes += ast_adsi_set_keys(buf + bytes, keys);
03559 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03560
03561 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03562 }
03563
03564 static void adsi_delete(struct ast_channel *chan, struct vm_state *vms)
03565 {
03566 int bytes=0;
03567 unsigned char buf[256];
03568 unsigned char keys[8];
03569
03570 int x;
03571
03572 if (!ast_adsi_available(chan))
03573 return;
03574
03575
03576 for (x=0;x<5;x++)
03577 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 6 + x);
03578
03579 keys[6] = 0x0;
03580 keys[7] = 0x0;
03581
03582 if (!vms->curmsg) {
03583
03584 keys[0] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03585 }
03586 if (vms->curmsg >= vms->lastmsg) {
03587
03588 if (vms->curmsg) {
03589
03590 keys[3] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 1);
03591 } else {
03592
03593 keys[3] = 1;
03594 }
03595 }
03596
03597
03598 if (vms->deleted[vms->curmsg])
03599 keys[1] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 11);
03600
03601
03602 keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
03603 bytes += ast_adsi_set_keys(buf + bytes, keys);
03604 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03605
03606 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03607 }
03608
03609 static void adsi_status(struct ast_channel *chan, struct vm_state *vms)
03610 {
03611 unsigned char buf[256] = "";
03612 char buf1[256] = "", buf2[256] = "";
03613 int bytes=0;
03614 unsigned char keys[8];
03615 int x;
03616
03617 char *newm = (vms->newmessages == 1) ? "message" : "messages";
03618 char *oldm = (vms->oldmessages == 1) ? "message" : "messages";
03619 if (!ast_adsi_available(chan))
03620 return;
03621 if (vms->newmessages) {
03622 snprintf(buf1, sizeof(buf1), "You have %d new", vms->newmessages);
03623 if (vms->oldmessages) {
03624 strncat(buf1, " and", sizeof(buf1) - strlen(buf1) - 1);
03625 snprintf(buf2, sizeof(buf2), "%d old %s.", vms->oldmessages, oldm);
03626 } else {
03627 snprintf(buf2, sizeof(buf2), "%s.", newm);
03628 }
03629 } else if (vms->oldmessages) {
03630 snprintf(buf1, sizeof(buf1), "You have %d old", vms->oldmessages);
03631 snprintf(buf2, sizeof(buf2), "%s.", oldm);
03632 } else {
03633 strcpy(buf1, "You have no messages.");
03634 buf2[0] = ' ';
03635 buf2[1] = '\0';
03636 }
03637 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03638 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03639 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03640
03641 for (x=0;x<6;x++)
03642 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
03643 keys[6] = 0;
03644 keys[7] = 0;
03645
03646
03647 if (vms->lastmsg < 0)
03648 keys[0] = 1;
03649 bytes += ast_adsi_set_keys(buf + bytes, keys);
03650
03651 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03652
03653 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03654 }
03655
03656 static void adsi_status2(struct ast_channel *chan, struct vm_state *vms)
03657 {
03658 unsigned char buf[256] = "";
03659 char buf1[256] = "", buf2[256] = "";
03660 int bytes=0;
03661 unsigned char keys[8];
03662 int x;
03663
03664 char *mess = (vms->lastmsg == 0) ? "message" : "messages";
03665
03666 if (!ast_adsi_available(chan))
03667 return;
03668
03669
03670 for (x=0;x<6;x++)
03671 keys[x] = ADSI_KEY_SKT | (ADSI_KEY_APPS + x);
03672
03673 keys[6] = 0;
03674 keys[7] = 0;
03675
03676 if ((vms->lastmsg + 1) < 1)
03677 keys[0] = 0;
03678
03679 snprintf(buf1, sizeof(buf1), "%s%s has", vms->curbox,
03680 strcasecmp(vms->curbox, "INBOX") ? " folder" : "");
03681
03682 if (vms->lastmsg + 1)
03683 snprintf(buf2, sizeof(buf2), "%d %s.", vms->lastmsg + 1, mess);
03684 else
03685 strcpy(buf2, "no messages.");
03686 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 1, ADSI_JUST_LEFT, 0, buf1, "");
03687 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_LEFT, 0, buf2, "");
03688 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, "", "");
03689 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03690 bytes += ast_adsi_set_keys(buf + bytes, keys);
03691
03692 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03693
03694 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03695
03696 }
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712 static void adsi_goodbye(struct ast_channel *chan)
03713 {
03714 unsigned char buf[256];
03715 int bytes=0;
03716
03717 if (!ast_adsi_available(chan))
03718 return;
03719 bytes += adsi_logo(buf + bytes);
03720 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
03721 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
03722 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
03723 bytes += ast_adsi_voice_mode(buf + bytes, 0);
03724
03725 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
03726 }
03727
03728
03729
03730
03731
03732 static int get_folder(struct ast_channel *chan, int start)
03733 {
03734 int x;
03735 int d;
03736 char fn[PATH_MAX];
03737 d = ast_play_and_wait(chan, "vm-press");
03738 if (d)
03739 return d;
03740 for (x = start; x< 5; x++) {
03741 if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, chan->language, (char *) NULL)))
03742 return d;
03743 d = ast_play_and_wait(chan, "vm-for");
03744 if (d)
03745 return d;
03746 snprintf(fn, sizeof(fn), "vm-%s", mbox(x));
03747 d = vm_play_folder_name(chan, fn);
03748 if (d)
03749 return d;
03750 d = ast_waitfordigit(chan, 500);
03751 if (d)
03752 return d;
03753 }
03754 d = ast_play_and_wait(chan, "vm-tocancel");
03755 if (d)
03756 return d;
03757 d = ast_waitfordigit(chan, 4000);
03758 return d;
03759 }
03760
03761 static int get_folder2(struct ast_channel *chan, char *fn, int start)
03762 {
03763 int res = 0;
03764 res = ast_play_and_wait(chan, fn);
03765 while (((res < '0') || (res > '9')) &&
03766 (res != '#') && (res >= 0)) {
03767 res = get_folder(chan, 0);
03768 }
03769 return res;
03770 }
03771
03772 static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vmfmts,
03773 char *context, signed char record_gain, long *duration, struct vm_state *vms)
03774 {
03775 int cmd = 0;
03776 int retries = 0;
03777 signed char zero_gain = 0;
03778
03779 while ((cmd >= 0) && (cmd != 't') && (cmd != '*')) {
03780 if (cmd)
03781 retries = 0;
03782 switch (cmd) {
03783 case '1':
03784
03785 {
03786 char msgfile[PATH_MAX];
03787 char textfile[PATH_MAX];
03788 int prepend_duration = 0;
03789 struct ast_config *msg_cfg;
03790 const char *duration_str;
03791
03792 make_file(msgfile, sizeof(msgfile), curdir, curmsg);
03793 strcpy(textfile, msgfile);
03794 strncat(textfile, ".txt", sizeof(textfile) - 1);
03795 *duration = 0;
03796
03797
03798 if (!(msg_cfg = ast_config_load(textfile))) {
03799 cmd = 0;
03800 break;
03801 }
03802
03803 if (record_gain)
03804 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
03805
03806 cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vmfmts, &prepend_duration, 1, silencethreshold, maxsilence);
03807 if (record_gain)
03808 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
03809
03810
03811 if ((duration_str = ast_variable_retrieve(msg_cfg, "message", "duration")))
03812 *duration = atoi(duration_str);
03813
03814 if (prepend_duration) {
03815 struct ast_category *msg_cat;
03816
03817 char duration_str[12];
03818
03819 *duration += prepend_duration;
03820 msg_cat = ast_category_get(msg_cfg, "message");
03821 snprintf(duration_str, 11, "%ld", *duration);
03822 if (!ast_variable_update(msg_cat, "duration", duration_str, NULL, 0)) {
03823 config_text_file_save(textfile, msg_cfg, "app_voicemail");
03824 STORE(curdir, vmu->mailbox, context, curmsg, chan, vmu, vmfmts, *duration, vms);
03825 }
03826 }
03827
03828 ast_config_destroy(msg_cfg);
03829
03830 break;
03831 }
03832 case '2':
03833 cmd = 't';
03834 break;
03835 case '*':
03836 cmd = '*';
03837 break;
03838 default:
03839 cmd = ast_play_and_wait(chan,"vm-forwardoptions");
03840
03841 if (!cmd)
03842 cmd = ast_play_and_wait(chan,"vm-starmain");
03843
03844 if (!cmd)
03845 cmd = ast_waitfordigit(chan,6000);
03846 if (!cmd)
03847 retries++;
03848 if (retries > 3)
03849 cmd = 't';
03850 }
03851 }
03852 if (cmd == 't' || cmd == 'S')
03853 cmd = 0;
03854 return cmd;
03855 }
03856
03857 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
03858 {
03859 char todir[PATH_MAX], fn[PATH_MAX], ext_context[PATH_MAX], *stringp;
03860 int newmsgs = 0, oldmsgs = 0;
03861 const char *category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY");
03862
03863 make_dir(todir, sizeof(todir), vmu->context, vmu->mailbox, "INBOX");
03864 make_file(fn, sizeof(fn), todir, msgnum);
03865 snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context);
03866
03867 if (!ast_strlen_zero(vmu->attachfmt)) {
03868 if (strstr(fmt, vmu->attachfmt)) {
03869 fmt = vmu->attachfmt;
03870 } else {
03871 ast_log(LOG_WARNING, "Attachment format '%s' is not one of the recorded formats '%s'. Falling back to default format for '%s@%s'.\n", vmu->attachfmt, fmt, vmu->mailbox, vmu->context);
03872 }
03873 }
03874
03875
03876 fmt = ast_strdupa(fmt);
03877 stringp = fmt;
03878 strsep(&stringp, "|");
03879
03880 if (!ast_strlen_zero(vmu->email)) {
03881 int attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
03882 char *myserveremail = serveremail;
03883 attach_user_voicemail = ast_test_flag(vmu, VM_ATTACH);
03884 if (!ast_strlen_zero(vmu->serveremail))
03885 myserveremail = vmu->serveremail;
03886
03887 if (attach_user_voicemail)
03888 RETRIEVE(todir, msgnum);
03889
03890
03891 sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, fn, fmt, duration, attach_user_voicemail, chan, category);
03892
03893 if (attach_user_voicemail)
03894 DISPOSE(todir, msgnum);
03895 }
03896
03897 if (!ast_strlen_zero(vmu->pager)) {
03898 char *myserveremail = serveremail;
03899 if (!ast_strlen_zero(vmu->serveremail))
03900 myserveremail = vmu->serveremail;
03901 sendpage(myserveremail, vmu->pager, msgnum, vmu->context, vmu->mailbox, cidnum, cidname, duration, vmu, category);
03902 }
03903
03904 if (ast_test_flag(vmu, VM_DELETE)) {
03905 DELETE(todir, msgnum, fn);
03906 }
03907
03908 #ifdef IMAP_STORAGE
03909 DELETE(todir, msgnum, fn);
03910 #endif
03911
03912 if (ast_app_has_voicemail(ext_context, NULL)) {
03913 ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs);
03914 }
03915 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);
03916 run_externnotify(vmu->context, vmu->mailbox);
03917 return 0;
03918 }
03919
03920 static int forward_message(struct ast_channel *chan, char *context, struct vm_state *vms, struct ast_vm_user *sender, char *fmt, int flag, signed char record_gain)
03921 {
03922 #ifdef IMAP_STORAGE
03923 BODY *body;
03924 char *header_content;
03925 char *temp;
03926 char todir[256];
03927 int todircount=0;
03928 struct vm_state *dstvms;
03929 #endif
03930 char username[70]="";
03931 int res = 0, cmd = 0;
03932 struct ast_vm_user *receiver = NULL, *vmtmp;
03933 AST_LIST_HEAD_NOLOCK_STATIC(extensions, ast_vm_user);
03934 char *stringp;
03935 const char *s;
03936 int saved_messages = 0, found = 0;
03937 int valid_extensions = 0;
03938 char *dir;
03939 int curmsg;
03940
03941 if (vms == NULL) return -1;
03942 dir = vms->curdir;
03943 curmsg = vms->curmsg;
03944
03945 while (!res && !valid_extensions) {
03946 int use_directory = 0;
03947 if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
03948 int done = 0;
03949 int retries = 0;
03950 cmd=0;
03951 while ((cmd >= 0) && !done ){
03952 if (cmd)
03953 retries = 0;
03954 switch (cmd) {
03955 case '1':
03956 use_directory = 0;
03957 done = 1;
03958 break;
03959 case '2':
03960 use_directory = 1;
03961 done=1;
03962 break;
03963 case '*':
03964 cmd = 't';
03965 done = 1;
03966 break;
03967 default:
03968
03969 cmd = ast_play_and_wait(chan,"vm-forward");
03970 if (!cmd)
03971 cmd = ast_waitfordigit(chan,3000);
03972 if (!cmd)
03973 retries++;
03974 if (retries > 3)
03975 {
03976 cmd = 't';
03977 done = 1;
03978 }
03979
03980 }
03981 }
03982 if (cmd < 0 || cmd == 't')
03983 break;
03984 }
03985
03986 if (use_directory) {
03987
03988
03989 char old_context[sizeof(chan->context)];
03990 char old_exten[sizeof(chan->exten)];
03991 int old_priority;
03992 struct ast_app* app;
03993
03994
03995 app = pbx_findapp("Directory");
03996 if (app) {
03997 char vmcontext[256];
03998
03999 memcpy(old_context, chan->context, sizeof(chan->context));
04000 memcpy(old_exten, chan->exten, sizeof(chan->exten));
04001 old_priority = chan->priority;
04002
04003
04004 sprintf(vmcontext, "%s||v", context ? context : "default");
04005 res = pbx_exec(chan, app, vmcontext);
04006
04007 ast_copy_string(username, chan->exten, sizeof(username));
04008
04009
04010 memcpy(chan->context, old_context, sizeof(chan->context));
04011 memcpy(chan->exten, old_exten, sizeof(chan->exten));
04012 chan->priority = old_priority;
04013
04014 } else {
04015 ast_log(LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
04016 ast_clear_flag((&globalflags), VM_DIRECFORWARD);
04017 }
04018 } else {
04019
04020 res = ast_streamfile(chan, "vm-extension", chan->language);
04021 if (res)
04022 break;
04023 if ((res = ast_readstring(chan, username, sizeof(username) - 1, 2000, 10000, "#") < 0))
04024 break;
04025 }
04026
04027
04028 if (ast_strlen_zero(username))
04029 continue;
04030 stringp = username;
04031 s = strsep(&stringp, "*");
04032
04033 valid_extensions = 1;
04034 while (s) {
04035
04036 if (strcmp(s,sender->mailbox) && (receiver = find_user(NULL, context, s))) {
04037 AST_LIST_INSERT_HEAD(&extensions, receiver, list);
04038 found++;
04039 } else {
04040 valid_extensions = 0;
04041 break;
04042 }
04043 s = strsep(&stringp, "*");
04044 }
04045
04046 if (valid_extensions)
04047 break;
04048
04049 res = ast_play_and_wait(chan, "pbx-invalid");
04050 }
04051
04052 if (AST_LIST_EMPTY(&extensions) || !valid_extensions)
04053 return res;
04054 if (flag==1) {
04055 struct leave_vm_options leave_options;
04056 char mailbox[AST_MAX_EXTENSION * 2 + 2];
04057 snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context);
04058
04059
04060 memset(&leave_options, 0, sizeof(leave_options));
04061 leave_options.record_gain = record_gain;
04062 cmd = leave_voicemail(chan, mailbox, &leave_options);
04063 } else {
04064
04065
04066 long duration = 0;
04067 RETRIEVE(dir, curmsg);
04068 cmd = vm_forwardoptions(chan, sender, dir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, vms);
04069 if (!cmd) {
04070 AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) {
04071 #ifdef IMAP_STORAGE
04072 char *myserveremail;
04073 int attach_user_voicemail;
04074
04075 if(option_debug > 2)
04076 ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
04077 if (vms->msgArray[vms->curmsg] == 0) {
04078 ast_log (LOG_WARNING,"Trying to access unknown message\n");
04079 return -1;
04080 }
04081
04082
04083 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
04084
04085 if (ast_strlen_zero(header_content)) {
04086 ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[vms->curmsg]);
04087 return -1;
04088 }
04089
04090 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:");
04091 if (temp)
04092 duration = atoi(temp);
04093 else
04094 duration = 0;
04095
04096
04097 fmt = ast_strdupa(fmt);
04098 if (fmt) {
04099 stringp = fmt;
04100 strsep(&stringp, "|");
04101 } else {
04102 ast_log (LOG_ERROR,"audio format not set. Default to WAV\n");
04103 fmt = "WAV";
04104 }
04105 if (!strcasecmp(fmt, "wav49"))
04106 fmt = "WAV";
04107 if(option_debug > 2)
04108 ast_log (LOG_DEBUG,"**** format set to %s, vmfmts set to %s\n",fmt,vmfmts);
04109
04110
04111 snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmtmp->context, vmtmp->mailbox);
04112 make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
04113 if(option_debug > 2)
04114 ast_log (LOG_DEBUG,"Before mail_fetchstructure, message number is %ld, filename is:%s\n",vms->msgArray[vms->curmsg], vms->fn);
04115
04116 mail_fetchstructure (vms->mailstream, vms->msgArray[vms->curmsg], &body);
04117 save_body(body,vms,"3","gsm");
04118
04119 save_body(body,vms,"2",fmt);
04120
04121
04122 dstvms = get_vm_state_by_mailbox(vmtmp->mailbox,0);
04123 if (dstvms) {
04124 init_mailstream(dstvms, 0);
04125 if (!dstvms->mailstream) {
04126 ast_log (LOG_ERROR,"IMAP mailstream for %s is NULL\n",vmtmp->mailbox);
04127 } else {
04128 STORE(todir, vmtmp->mailbox, vmtmp->context, dstvms->curmsg, chan, vmtmp, fmt, duration, dstvms);
04129 run_externnotify(vmtmp->context, vmtmp->mailbox);
04130 }
04131 } else {
04132 ast_log (LOG_ERROR,"Could not find state information for mailbox %s\n",vmtmp->mailbox);
04133 }
04134
04135 myserveremail = serveremail;
04136 if (!ast_strlen_zero(vmtmp->serveremail))
04137 myserveremail = vmtmp->serveremail;
04138 attach_user_voicemail = ast_test_flag((&globalflags), VM_ATTACH);
04139 attach_user_voicemail = ast_test_flag(vmtmp, VM_ATTACH);
04140
04141 sendmail(myserveremail, vmtmp, todircount, vmtmp->context, vmtmp->mailbox, S_OR(chan->cid.cid_num, NULL), S_OR(chan->cid.cid_name, NULL), vms->fn, fmt, duration, attach_user_voicemail, chan, NULL);
04142 #else
04143 copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir);
04144 #endif
04145 saved_messages++;
04146 AST_LIST_REMOVE_CURRENT(&extensions, list);
04147 free_user(vmtmp);
04148 if (res)
04149 break;
04150 }
04151 AST_LIST_TRAVERSE_SAFE_END;
04152 if (saved_messages > 0) {
04153
04154
04155
04156
04157
04158
04159
04160
04161 res = ast_play_and_wait(chan, "vm-msgsaved");
04162 }
04163 }
04164 }
04165
04166
04167 while ((vmtmp = AST_LIST_REMOVE_HEAD(&extensions, list)))
04168 free_user(vmtmp);
04169 return res ? res : cmd;
04170 }
04171
04172 static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file)
04173 {
04174 int res;
04175 if ((res = ast_stream_and_wait(chan, file, chan->language, AST_DIGIT_ANY)) < 0)
04176 ast_log(LOG_WARNING, "Unable to play message %s\n", file);
04177 return res;
04178 }
04179
04180 static int wait_file(struct ast_channel *chan, struct vm_state *vms, char *file)
04181 {
04182 return ast_control_streamfile(chan, file, "#", "*", "1456789", "0", "2", skipms);
04183 }
04184
04185 static int play_message_category(struct ast_channel *chan, const char *category)
04186 {
04187 int res = 0;
04188
04189 if (!ast_strlen_zero(category))
04190 res = ast_play_and_wait(chan, category);
04191
04192 if (res) {
04193 ast_log(LOG_WARNING, "No sound file for category '%s' was found.\n", category);
04194 res = 0;
04195 }
04196
04197 return res;
04198 }
04199
04200 static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename)
04201 {
04202 int res = 0;
04203 struct vm_zone *the_zone = NULL;
04204 time_t t;
04205
04206 if (ast_get_time_t(origtime, &t, 0, NULL)) {
04207 ast_log(LOG_WARNING, "Couldn't find origtime in %s\n", filename);
04208 return 0;
04209 }
04210
04211
04212 if (!ast_strlen_zero(vmu->zonetag)) {
04213
04214 struct vm_zone *z;
04215 AST_LIST_LOCK(&zones);
04216 AST_LIST_TRAVERSE(&zones, z, list) {
04217 if (!strcmp(z->name, vmu->zonetag)) {
04218 the_zone = z;
04219 break;
04220 }
04221 }
04222 AST_LIST_UNLOCK(&zones);
04223 }
04224
04225
04226 #if 0
04227
04228 ast_localtime(&t, &time_now, NULL);
04229 tv_now = ast_tvnow();
04230 tnow = tv_now.tv_sec;
04231 ast_localtime(&tnow, &time_then, NULL);
04232
04233
04234 if (time_now.tm_year == time_then.tm_year)
04235 snprintf(temp,sizeof(temp),"%d",time_now.tm_yday);
04236 else
04237 snprintf(temp,sizeof(temp),"%d",(time_now.tm_year - time_then.tm_year) * 365 + (time_now.tm_yday - time_then.tm_yday));
04238 pbx_builtin_setvar_helper(chan, "DIFF_DAY", temp);
04239
04240
04241 #endif
04242 if (the_zone)
04243 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, the_zone->msg_format, the_zone->timezone);
04244 else if (!strcasecmp(chan->language,"pl"))
04245 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q HM", NULL);
04246 else if (!strcasecmp(chan->language,"se"))
04247 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' dB 'digits/at' k 'and' M", NULL);
04248 else if (!strcasecmp(chan->language,"no"))
04249 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
04250 else if (!strcasecmp(chan->language,"de"))
04251 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' Q 'digits/at' HM", NULL);
04252 else if (!strcasecmp(chan->language,"nl"))
04253 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/nl-om' HM", NULL);
04254 else if (!strcasecmp(chan->language,"it"))
04255 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);
04256 else if (!strcasecmp(chan->language,"gr"))
04257 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q H 'digits/kai' M ", NULL);
04258 else if (!strcasecmp(chan->language,"pt_BR"))
04259 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);
04260 else
04261 res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, chan->language, "'vm-received' q 'digits/at' IMp", NULL);
04262 #if 0
04263 pbx_builtin_setvar_helper(chan, "DIFF_DAY", NULL);
04264 #endif
04265 return res;
04266 }
04267
04268
04269
04270 static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, char *cid, const char *context, int callback)
04271 {
04272 int res = 0;
04273 int i;
04274 char *callerid, *name;
04275 char prefile[PATH_MAX] = "";
04276
04277
04278
04279
04280 if ((cid == NULL)||(context == NULL))
04281 return res;
04282
04283
04284 if (option_debug > 2)
04285 ast_log(LOG_DEBUG, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context);
04286 ast_callerid_parse(cid, &name, &callerid);
04287 if ((!ast_strlen_zero(callerid)) && strcmp(callerid, "Unknown")) {
04288
04289
04290 for (i = 0 ; i < MAX_NUM_CID_CONTEXTS ; i++){
04291 if (option_debug > 2)
04292 ast_log(LOG_DEBUG, "VM-CID: comparing internalcontext: %s\n", cidinternalcontexts[i]);
04293 if ((strcmp(cidinternalcontexts[i], context) == 0))
04294 break;
04295 }
04296 if (i != MAX_NUM_CID_CONTEXTS){
04297 if (!res) {
04298 snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, context, callerid);
04299 if (!ast_strlen_zero(prefile)) {
04300
04301 if (ast_fileexists(prefile, NULL, NULL) > 0) {
04302 if (option_verbose > 2)
04303 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: CID number '%s' matches mailbox number, playing recorded name\n", callerid);
04304 if (!callback)
04305 res = wait_file2(chan, vms, "vm-from");
04306 res = ast_stream_and_wait(chan, prefile, chan->language, "");
04307 } else {
04308 if (option_verbose > 2)
04309 ast_verbose(VERBOSE_PREFIX_3 "Playing envelope info: message from '%s'\n", callerid);
04310
04311 if (!callback)
04312 res = wait_file2(chan, vms, "vm-from-extension");
04313 res = ast_say_digit_str(chan, callerid, "", chan->language);
04314 }
04315 }
04316 }
04317 }
04318
04319 else if (!res){
04320 if (option_debug > 2)
04321 ast_log(LOG_DEBUG, "VM-CID: Numeric caller id: (%s)\n",callerid);
04322
04323 if (!callback)
04324 res = wait_file2(chan, vms, "vm-from-phonenumber");
04325 res = ast_say_digit_str(chan, callerid, AST_DIGIT_ANY, chan->language);
04326 }
04327 } else {
04328
04329 if (option_debug)
04330 ast_log(LOG_DEBUG, "VM-CID: From an unknown number\n");
04331
04332 res = wait_file2(chan, vms, "vm-unknown-caller");
04333 }
04334 return res;
04335 }
04336
04337 static int play_message_duration(struct ast_channel *chan, struct vm_state *vms, const char *duration, int minduration)
04338 {
04339 int res = 0;
04340 int durationm;
04341 int durations;
04342
04343 if (duration == NULL)
04344 return res;
04345
04346
04347 durations=atoi(duration);
04348 durationm=(durations / 60);
04349
04350 if (option_debug > 2)
04351 ast_log(LOG_DEBUG, "VM-Duration: duration is: %d seconds converted to: %d minutes\n", durations, durationm);
04352
04353 if ((!res) && (durationm >= minduration)) {
04354 res = wait_file2(chan, vms, "vm-duration");
04355
04356
04357 if (!strcasecmp(chan->language, "pl")) {
04358 div_t num = div(durationm, 10);
04359
04360 if (durationm == 1) {
04361 res = ast_play_and_wait(chan, "digits/1z");
04362 res = res ? res : ast_play_and_wait(chan, "vm-minute-ta");
04363 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
04364 if (num.rem == 2) {
04365 if (!num.quot) {
04366 res = ast_play_and_wait(chan, "digits/2-ie");
04367 } else {
04368 res = say_and_wait(chan, durationm - 2 , chan->language);
04369 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
04370 }
04371 } else {
04372 res = say_and_wait(chan, durationm, chan->language);
04373 }
04374 res = res ? res : ast_play_and_wait(chan, "vm-minute-ty");
04375 } else {
04376 res = say_and_wait(chan, durationm, chan->language);
04377 res = res ? res : ast_play_and_wait(chan, "vm-minute-t");
04378 }
04379
04380 } else {
04381 res = ast_say_number(chan, durationm, AST_DIGIT_ANY, chan->language, NULL);
04382 res = wait_file2(chan, vms, "vm-minutes");
04383 }
04384 }
04385 return res;
04386 }
04387
04388 #ifdef IMAP_STORAGE
04389 static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
04390 {
04391 BODY *body;
04392 char *header_content;
04393 char cid[256];
04394 char context[256];
04395 char origtime[32];
04396 char duration[16];
04397 char category[32];
04398 char todir[PATH_MAX];
04399 int res = 0;
04400 char *attachedfilefmt;
04401 char *temp;
04402
04403 vms->starting = 0;
04404 if(option_debug > 2)
04405 ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
04406 if (vms->msgArray[vms->curmsg] == 0) {
04407 ast_log (LOG_WARNING,"Trying to access unknown message\n");
04408 return -1;
04409 }
04410
04411
04412 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
04413
04414 if (ast_strlen_zero(header_content)) {
04415 ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[vms->curmsg]);
04416 return -1;
04417 }
04418 snprintf(todir, sizeof(todir), "%s%s/%s/tmp", VM_SPOOL_DIR, vmu->context, vmu->mailbox);
04419 make_gsm_file(vms->fn, vms->imapuser, todir, vms->curmsg);
04420
04421 mail_fetchstructure (vms->mailstream,vms->msgArray[vms->curmsg],&body);
04422
04423
04424 if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
04425 attachedfilefmt = ast_strdupa(body->nested.part->next->body.parameter->value);
04426 } else {
04427 ast_log(LOG_ERROR, "There is no file attached to this IMAP message.\n");
04428 return -1;
04429 }
04430
04431
04432
04433 strsep(&attachedfilefmt, ".");
04434 if (!attachedfilefmt) {
04435 ast_log(LOG_ERROR, "File format could not be obtained from IMAP message attachment\n");
04436 return -1;
04437 }
04438 save_body(body, vms, "2", attachedfilefmt);
04439
04440 adsi_message(chan, vms);
04441 if (!vms->curmsg)
04442 res = wait_file2(chan, vms, "vm-first");
04443 else if (vms->curmsg == vms->lastmsg)
04444 res = wait_file2(chan, vms, "vm-last");
04445 if (!res) {
04446 res = wait_file2(chan, vms, "vm-message");
04447 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
04448 if (!res)
04449 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, (char *) NULL);
04450 }
04451 }
04452
04453
04454 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:");
04455
04456 if (temp)
04457 ast_copy_string(cid, temp, sizeof(cid));
04458 else
04459 cid[0] = '\0';
04460
04461 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:");
04462
04463 if (temp)
04464 ast_copy_string(context, temp, sizeof(context));
04465 else
04466 context[0] = '\0';
04467
04468 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:");
04469
04470 if (temp)
04471 ast_copy_string(origtime, temp, sizeof(origtime));
04472 else
04473 origtime[0] = '\0';
04474
04475 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Duration:");
04476
04477 if (temp)
04478 ast_copy_string(duration,temp, sizeof(duration));
04479 else
04480 duration[0] = '\0';
04481
04482 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Category:");
04483
04484 if (temp)
04485 ast_copy_string(category,temp, sizeof(category));
04486 else
04487 category[0] = '\0';
04488
04489
04490
04491 if (res == '1')
04492 res = 0;
04493
04494 if ((!res) && !ast_strlen_zero(category)) {
04495 res = play_message_category(chan, category);
04496 }
04497
04498 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)) && origtime[0] != '\0')
04499 res = play_message_datetime(chan, vmu, origtime, "IMAP_STORAGE");
04500 if ((!res) && (ast_test_flag(vmu, VM_SAYCID)) && cid[0] !='\0' && context[0] !='\0')
04501 res = play_message_callerid(chan, vms, cid, context, 0);
04502
04503 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)) && duration[0] != '\0')
04504 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
04505
04506
04507
04508
04509
04510
04511 res = 0;
04512
04513 if (!res) {
04514 vms->heard[vms->curmsg] = 1;
04515 res = wait_file(chan, vms, vms->fn);
04516 }
04517 DISPOSE(vms->curdir, vms->curmsg);
04518 DELETE(0, 0, vms->fn);
04519 return res;
04520 }
04521 #else
04522 static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
04523 {
04524 int res = 0;
04525 char filename[256], *cid;
04526 const char *origtime, *context, *category, *duration;
04527 struct ast_config *msg_cfg;
04528
04529 vms->starting = 0;
04530 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
04531 adsi_message(chan, vms);
04532 if (!vms->curmsg)
04533 res = wait_file2(chan, vms, "vm-first");
04534 else if (vms->curmsg == vms->lastmsg)
04535 res = wait_file2(chan, vms, "vm-last");
04536 if (!res) {
04537
04538 if (!strcasecmp(chan->language, "pl")) {
04539 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
04540 int ten, one;
04541 char nextmsg[256];
04542 ten = (vms->curmsg + 1) / 10;
04543 one = (vms->curmsg + 1) % 10;
04544
04545 if (vms->curmsg < 20) {
04546 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", vms->curmsg + 1);
04547 res = wait_file2(chan, vms, nextmsg);
04548 } else {
04549 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", ten * 10);
04550 res = wait_file2(chan, vms, nextmsg);
04551 if (one > 0) {
04552 if (!res) {
04553 snprintf(nextmsg, sizeof(nextmsg), "digits/n-%d", one);
04554 res = wait_file2(chan, vms, nextmsg);
04555 }
04556 }
04557 }
04558 }
04559 if (!res)
04560 res = wait_file2(chan, vms, "vm-message");
04561 } else {
04562 if (!strcasecmp(chan->language, "se"))
04563 res = wait_file2(chan, vms, "vm-meddelandet");
04564 else
04565 res = wait_file2(chan, vms, "vm-message");
04566 if (vms->curmsg && (vms->curmsg != vms->lastmsg)) {
04567 if (!res)
04568 res = ast_say_number(chan, vms->curmsg + 1, AST_DIGIT_ANY, chan->language, NULL);
04569 }
04570 }
04571 }
04572
04573
04574 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
04575 snprintf(filename, sizeof(filename), "%s.txt", vms->fn2);
04576 RETRIEVE(vms->curdir, vms->curmsg);
04577 msg_cfg = ast_config_load(filename);
04578 if (!msg_cfg) {
04579 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
04580 return 0;
04581 }
04582
04583 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
04584 ast_log(LOG_WARNING, "No origtime?!\n");
04585 DISPOSE(vms->curdir, vms->curmsg);
04586 ast_config_destroy(msg_cfg);
04587 return 0;
04588 }
04589
04590 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
04591 duration = ast_variable_retrieve(msg_cfg, "message", "duration");
04592 category = ast_variable_retrieve(msg_cfg, "message", "category");
04593
04594 context = ast_variable_retrieve(msg_cfg, "message", "context");
04595 if (!strncasecmp("macro",context,5))
04596 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
04597 if (!res)
04598 res = play_message_category(chan, category);
04599 if ((!res) && (ast_test_flag(vmu, VM_ENVELOPE)))
04600 res = play_message_datetime(chan, vmu, origtime, filename);
04601 if ((!res) && (ast_test_flag(vmu, VM_SAYCID)))
04602 res = play_message_callerid(chan, vms, cid, context, 0);
04603 if ((!res) && (ast_test_flag(vmu, VM_SAYDURATION)))
04604 res = play_message_duration(chan, vms, duration, vmu->saydurationm);
04605
04606 if (res == '1')
04607 res = 0;
04608 ast_config_destroy(msg_cfg);
04609
04610 if (!res) {
04611 make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg);
04612 vms->heard[vms->curmsg] = 1;
04613 res = wait_file(chan, vms, vms->fn);
04614 }
04615 DISPOSE(vms->curdir, vms->curmsg);
04616 return res;
04617 }
04618 #endif
04619
04620 #ifdef IMAP_STORAGE
04621 static void imap_mailbox_name(char *spec, struct vm_state *vms, int box, int use_folder)
04622 {
04623 char tmp[256], *t = tmp;
04624 size_t left = sizeof(tmp);
04625
04626 if (box == 1) {
04627 ast_copy_string(vms->curbox, mbox(0), sizeof(vms->curbox));
04628 sprintf(vms->vmbox, "vm-%s", mbox(1));
04629 } else {
04630 ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
04631 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
04632 }
04633
04634
04635 ast_build_string(&t, &left, "{%s:%s/imap", imapserver, imapport);
04636
04637
04638 if (!ast_strlen_zero(authuser))
04639 ast_build_string(&t, &left, "/authuser=%s", authuser);
04640
04641
04642 if (!ast_strlen_zero(imapflags))
04643 ast_build_string(&t, &left, "/%s", imapflags);
04644
04645
04646 ast_build_string(&t, &left, "/user=%s}", vms->imapuser);
04647
04648 if(box == 0 || box == 1)
04649 sprintf(spec, "%s%s", tmp, use_folder? imapfolder: "INBOX");
04650 else
04651 sprintf(spec, "%s%s%c%s", tmp, imapfolder, delimiter, mbox(box));
04652 }
04653
04654 static int init_mailstream(struct vm_state *vms, int box)
04655 {
04656 MAILSTREAM *stream = NIL;
04657 long debug;
04658 char tmp[255];
04659
04660 if (!vms) {
04661 ast_log (LOG_ERROR,"vm_state is NULL!\n");
04662 return -1;
04663 }
04664 if(option_debug > 2)
04665 ast_log (LOG_DEBUG,"vm_state user is:%s\n",vms->imapuser);
04666 if (vms->mailstream == NIL || !vms->mailstream) {
04667 if (option_debug)
04668 ast_log (LOG_DEBUG,"mailstream not set.\n");
04669 } else {
04670 stream = vms->mailstream;
04671 }
04672
04673 debug = NIL;
04674
04675 if (delimiter == '\0') {
04676 char *cp;
04677 #include "linkage.c"
04678
04679 imap_mailbox_name(tmp, vms, 0, 0);
04680 stream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
04681 if (stream == NIL) {
04682 ast_log (LOG_ERROR, "Can't connect to imap server %s\n", tmp);
04683 return NIL;
04684 }
04685 get_mailbox_delimiter(stream);
04686
04687 for(cp = imapfolder; *cp; cp++)
04688 if(*cp == '/')
04689 *cp = delimiter;
04690 }
04691
04692 imap_mailbox_name(tmp, vms, box, 1);
04693 if(option_debug > 2)
04694 ast_log (LOG_DEBUG,"Before mail_open, server: %s, box:%d\n", tmp, box);
04695 vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
04696 if (vms->mailstream == NIL) {
04697 return -1;
04698 } else {
04699 return 0;
04700 }
04701 }
04702
04703 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box)
04704 {
04705 SEARCHPGM *pgm;
04706 SEARCHHEADER *hdr;
04707 int ret;
04708 char dbox[256];
04709
04710 ast_copy_string(vms->imapuser,vmu->imapuser, sizeof(vms->imapuser));
04711 if(option_debug > 2)
04712 ast_log(LOG_DEBUG,"Before init_mailstream, user is %s\n",vmu->imapuser);
04713 ret = init_mailstream(vms, box);
04714 if (ret != 0 || !vms->mailstream) {
04715 ast_log (LOG_ERROR,"Could not initialize mailstream\n");
04716 return -1;
04717 }
04718
04719
04720 mail_parameters(NULL, SET_QUOTA, (void *) mm_parsequota);
04721 imap_mailbox_name(dbox, vms, box, 1);
04722 imap_getquotaroot(vms->mailstream, dbox);
04723
04724 pgm = mail_newsearchpgm();
04725
04726
04727 hdr = mail_newsearchheader ("X-Asterisk-VM-Extension", vmu->mailbox);
04728 pgm->header = hdr;
04729 pgm->deleted = 0;
04730 pgm->undeleted = 1;
04731
04732
04733 if (box == 0) {
04734 pgm->unseen = 1;
04735 pgm->seen = 0;
04736 } else if (box == 1) {
04737 pgm->seen = 1;
04738 pgm->unseen = 0;
04739 }
04740
04741 vms->vmArrayIndex = 0;
04742 if(option_debug > 2)
04743 ast_log(LOG_DEBUG,"Before mail_search_full, user is %s\n",vmu->imapuser);
04744 mail_search_full (vms->mailstream, NULL, pgm, NIL);
04745
04746
04747 vms->lastmsg = vms->vmArrayIndex - 1;
04748
04749 mail_free_searchpgm(&pgm);
04750 return 0;
04751 }
04752 #else
04753 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box)
04754 {
04755 int res = 0;
04756 int count_msg, last_msg;
04757
04758 ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox));
04759
04760
04761
04762
04763 snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox);
04764
04765
04766 create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox);
04767
04768 count_msg = count_messages(vmu, vms->curdir);
04769 if (count_msg < 0)
04770 return count_msg;
04771 else
04772 vms->lastmsg = count_msg - 1;
04773
04774
04775
04776
04777
04778
04779
04780
04781 last_msg = last_message_index(vmu, vms->curdir);
04782 if (last_msg < 0)
04783 return last_msg;
04784 else if (vms->lastmsg != last_msg)
04785 {
04786 ast_log(LOG_NOTICE, "Resequencing Mailbox: %s\n", vms->curdir);
04787 res = resequence_mailbox(vmu, vms->curdir);
04788 if (res)
04789 return res;
04790 }
04791
04792 return 0;
04793 }
04794 #endif
04795
04796 static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu)
04797 {
04798 int x = 0;
04799 #ifndef IMAP_STORAGE
04800 int res = 0, nummsg;
04801 #endif
04802
04803 if (vms->lastmsg <= -1)
04804 goto done;
04805
04806 vms->curmsg = -1;
04807 #ifndef IMAP_STORAGE
04808
04809 if (vm_lock_path(vms->curdir))
04810 return ERROR_LOCK_PATH;
04811
04812 for (x = 0; x < vmu->maxmsg; x++) {
04813 if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) {
04814
04815 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
04816 if (!EXISTS(vms->curdir, x, vms->fn, NULL))
04817 break;
04818 vms->curmsg++;
04819 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
04820 if (strcmp(vms->fn, vms->fn2)) {
04821 RENAME(vms->curdir, x, vmu->mailbox,vmu->context, vms->curdir, vms->curmsg, vms->fn, vms->fn2);
04822 }
04823 } else if (!strcasecmp(vms->curbox, "INBOX") && vms->heard[x] && !vms->deleted[x]) {
04824
04825 res = save_to_folder(vmu, vms, x, 1);
04826 if (res == ERROR_LOCK_PATH) {
04827
04828 vms->deleted[x] = 0;
04829 vms->heard[x] = 0;
04830 --x;
04831 }
04832 }
04833 }
04834
04835
04836 nummsg = x - 1;
04837 for (x = vms->curmsg + 1; x <= nummsg; x++) {
04838 make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);
04839 if (EXISTS(vms->curdir, x, vms->fn, NULL))
04840 DELETE(vms->curdir, x, vms->fn);
04841 }
04842 ast_unlock_path(vms->curdir);
04843 #else
04844 if (vms->deleted) {
04845 for (x=0;x < vmu->maxmsg;x++) {
04846 if (vms->deleted[x]) {
04847 if(option_debug > 2)
04848 ast_log(LOG_DEBUG,"IMAP delete of %d\n",x);
04849 IMAP_DELETE(vms->curdir, x, vms->fn, vms);
04850 }
04851 }
04852 }
04853 #endif
04854
04855 done:
04856 if (vms->deleted)
04857 memset(vms->deleted, 0, vmu->maxmsg * sizeof(int));
04858 if (vms->heard)
04859 memset(vms->heard, 0, vmu->maxmsg * sizeof(int));
04860
04861 return 0;
04862 }
04863
04864
04865
04866
04867
04868
04869
04870 static int vm_play_folder_name_gr(struct ast_channel *chan, char *mbox)
04871 {
04872 int cmd;
04873 char *buf;
04874
04875 buf = alloca(strlen(mbox)+2);
04876 strcpy(buf, mbox);
04877 strcat(buf,"s");
04878
04879 if (!strcasecmp(mbox, "vm-INBOX") || !strcasecmp(mbox, "vm-Old")){
04880 cmd = ast_play_and_wait(chan, buf);
04881 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
04882 } else {
04883 cmd = ast_play_and_wait(chan, "vm-messages");
04884 return cmd ? cmd : ast_play_and_wait(chan, mbox);
04885 }
04886 }
04887
04888 static int vm_play_folder_name_pl(struct ast_channel *chan, char *mbox)
04889 {
04890 int cmd;
04891
04892 if (!strcasecmp(mbox, "vm-INBOX") || !strcasecmp(mbox, "vm-Old")) {
04893 if (!strcasecmp(mbox, "vm-INBOX"))
04894 cmd = ast_play_and_wait(chan, "vm-new-e");
04895 else
04896 cmd = ast_play_and_wait(chan, "vm-old-e");
04897 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
04898 } else {
04899 cmd = ast_play_and_wait(chan, "vm-messages");
04900 return cmd ? cmd : ast_play_and_wait(chan, mbox);
04901 }
04902 }
04903
04904 static int vm_play_folder_name_ua(struct ast_channel *chan, char *mbox)
04905 {
04906 int cmd;
04907
04908 if (!strcasecmp(mbox, "vm-Family") || !strcasecmp(mbox, "vm-Friends") || !strcasecmp(mbox, "vm-Work")){
04909 cmd = ast_play_and_wait(chan, "vm-messages");
04910 return cmd ? cmd : ast_play_and_wait(chan, mbox);
04911 } else {
04912 cmd = ast_play_and_wait(chan, mbox);
04913 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
04914 }
04915 }
04916
04917 static int vm_play_folder_name(struct ast_channel *chan, char *mbox)
04918 {
04919 int cmd;
04920
04921 if (!strcasecmp(chan->language, "it") || !strcasecmp(chan->language, "es") || !strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {
04922 cmd = ast_play_and_wait(chan, "vm-messages");
04923 return cmd ? cmd : ast_play_and_wait(chan, mbox);
04924 } else if (!strcasecmp(chan->language, "gr")){
04925 return vm_play_folder_name_gr(chan, mbox);
04926 } else if (!strcasecmp(chan->language, "pl")){
04927 return vm_play_folder_name_pl(chan, mbox);
04928 } else if (!strcasecmp(chan->language, "ua")){
04929 return vm_play_folder_name_ua(chan, mbox);
04930 } else {
04931 cmd = ast_play_and_wait(chan, mbox);
04932 return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
04933 }
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948 static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
04949 {
04950 int res = 0;
04951
04952 if (vms->newmessages) {
04953 res = ast_play_and_wait(chan, "vm-youhave");
04954 if (!res)
04955 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, NULL);
04956 if (!res) {
04957 if ((vms->newmessages == 1)) {
04958 res = ast_play_and_wait(chan, "vm-INBOX");
04959 if (!res)
04960 res = ast_play_and_wait(chan, "vm-message");
04961 } else {
04962 res = ast_play_and_wait(chan, "vm-INBOXs");
04963 if (!res)
04964 res = ast_play_and_wait(chan, "vm-messages");
04965 }
04966 }
04967 } else if (vms->oldmessages){
04968 res = ast_play_and_wait(chan, "vm-youhave");
04969 if (!res)
04970 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, NULL);
04971 if ((vms->oldmessages == 1)){
04972 res = ast_play_and_wait(chan, "vm-Old");
04973 if (!res)
04974 res = ast_play_and_wait(chan, "vm-message");
04975 } else {
04976 res = ast_play_and_wait(chan, "vm-Olds");
04977 if (!res)
04978 res = ast_play_and_wait(chan, "vm-messages");
04979 }
04980 } else if (!vms->oldmessages && !vms->newmessages)
04981 res = ast_play_and_wait(chan, "vm-denExeteMynhmata");
04982 return res;
04983 }
04984
04985
04986 static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms)
04987 {
04988 int res;
04989
04990
04991 res = ast_play_and_wait(chan, "vm-youhave");
04992 if (!res) {
04993 if (vms->newmessages) {
04994 res = say_and_wait(chan, vms->newmessages, chan->language);
04995 if (!res)
04996 res = ast_play_and_wait(chan, "vm-INBOX");
04997 if (vms->oldmessages && !res)
04998 res = ast_play_and_wait(chan, "vm-and");
04999 else if (!res) {
05000 if ((vms->newmessages == 1))
05001 res = ast_play_and_wait(chan, "vm-message");
05002 else
05003 res = ast_play_and_wait(chan, "vm-messages");
05004 }
05005
05006 }
05007 if (!res && vms->oldmessages) {
05008 res = say_and_wait(chan, vms->oldmessages, chan->language);
05009 if (!res)
05010 res = ast_play_and_wait(chan, "vm-Old");
05011 if (!res) {
05012 if (vms->oldmessages == 1)
05013 res = ast_play_and_wait(chan, "vm-message");
05014 else
05015 res = ast_play_and_wait(chan, "vm-messages");
05016 }
05017 }
05018 if (!res) {
05019 if (!vms->oldmessages && !vms->newmessages) {
05020 res = ast_play_and_wait(chan, "vm-no");
05021 if (!res)
05022 res = ast_play_and_wait(chan, "vm-messages");
05023 }
05024 }
05025 }
05026 return res;
05027 }
05028
05029
05030 static int vm_intro_it(struct ast_channel *chan, struct vm_state *vms)
05031 {
05032
05033 int res;
05034 if (!vms->oldmessages && !vms->newmessages)
05035 res = ast_play_and_wait(chan, "vm-no") ||
05036 ast_play_and_wait(chan, "vm-message");
05037 else
05038 res = ast_play_and_wait(chan, "vm-youhave");
05039 if (!res && vms->newmessages) {
05040 res = (vms->newmessages == 1) ?
05041 ast_play_and_wait(chan, "digits/un") ||
05042 ast_play_and_wait(chan, "vm-nuovo") ||
05043 ast_play_and_wait(chan, "vm-message") :
05044
05045 say_and_wait(chan, vms->newmessages, chan->language) ||
05046 ast_play_and_wait(chan, "vm-nuovi") ||
05047 ast_play_and_wait(chan, "vm-messages");
05048 if (!res && vms->oldmessages)
05049 res = ast_play_and_wait(chan, "vm-and");
05050 }
05051 if (!res && vms->oldmessages) {
05052 res = (vms->oldmessages == 1) ?
05053 ast_play_and_wait(chan, "digits/un") ||
05054 ast_play_and_wait(chan, "vm-vecchio") ||
05055 ast_play_and_wait(chan, "vm-message") :
05056
05057 say_and_wait(chan, vms->oldmessages, chan->language) ||
05058 ast_play_and_wait(chan, "vm-vecchi") ||
05059 ast_play_and_wait(chan, "vm-messages");
05060 }
05061 return res ? -1 : 0;
05062 }
05063
05064
05065 static int vm_intro_pl(struct ast_channel *chan, struct vm_state *vms)
05066 {
05067
05068 int res;
05069 div_t num;
05070
05071 if (!vms->oldmessages && !vms->newmessages) {
05072 res = ast_play_and_wait(chan, "vm-no");
05073 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05074 return res;
05075 } else {
05076 res = ast_play_and_wait(chan, "vm-youhave");
05077 }
05078
05079 if (vms->newmessages) {
05080 num = div(vms->newmessages, 10);
05081 if (vms->newmessages == 1) {
05082 res = ast_play_and_wait(chan, "digits/1-a");
05083 res = res ? res : ast_play_and_wait(chan, "vm-new-a");
05084 res = res ? res : ast_play_and_wait(chan, "vm-message");
05085 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
05086 if (num.rem == 2) {
05087 if (!num.quot) {
05088 res = ast_play_and_wait(chan, "digits/2-ie");
05089 } else {
05090 res = say_and_wait(chan, vms->newmessages - 2 , chan->language);
05091 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
05092 }
05093 } else {
05094 res = say_and_wait(chan, vms->newmessages, chan->language);
05095 }
05096 res = res ? res : ast_play_and_wait(chan, "vm-new-e");
05097 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05098 } else {
05099 res = say_and_wait(chan, vms->newmessages, chan->language);
05100 res = res ? res : ast_play_and_wait(chan, "vm-new-ych");
05101 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05102 }
05103 if (!res && vms->oldmessages)
05104 res = ast_play_and_wait(chan, "vm-and");
05105 }
05106 if (!res && vms->oldmessages) {
05107 num = div(vms->oldmessages, 10);
05108 if (vms->oldmessages == 1) {
05109 res = ast_play_and_wait(chan, "digits/1-a");
05110 res = res ? res : ast_play_and_wait(chan, "vm-old-a");
05111 res = res ? res : ast_play_and_wait(chan, "vm-message");
05112 } else if (num.rem > 1 && num.rem < 5 && num.quot != 1) {
05113 if (num.rem == 2) {
05114 if (!num.quot) {
05115 res = ast_play_and_wait(chan, "digits/2-ie");
05116 } else {
05117 res = say_and_wait(chan, vms->oldmessages - 2 , chan->language);
05118 res = res ? res : ast_play_and_wait(chan, "digits/2-ie");
05119 }
05120 } else {
05121 res = say_and_wait(chan, vms->oldmessages, chan->language);
05122 }
05123 res = res ? res : ast_play_and_wait(chan, "vm-old-e");
05124 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05125 } else {
05126 res = say_and_wait(chan, vms->oldmessages, chan->language);
05127 res = res ? res : ast_play_and_wait(chan, "vm-old-ych");
05128 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05129 }
05130 }
05131
05132 return res;
05133 }
05134
05135
05136 static int vm_intro_se(struct ast_channel *chan, struct vm_state *vms)
05137 {
05138
05139 int res;
05140
05141 res = ast_play_and_wait(chan, "vm-youhave");
05142 if (res)
05143 return res;
05144
05145 if (!vms->oldmessages && !vms->newmessages) {
05146 res = ast_play_and_wait(chan, "vm-no");
05147 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05148 return res;
05149 }
05150
05151 if (vms->newmessages) {
05152 if ((vms->newmessages == 1)) {
05153 res = ast_play_and_wait(chan, "digits/ett");
05154 res = res ? res : ast_play_and_wait(chan, "vm-nytt");
05155 res = res ? res : ast_play_and_wait(chan, "vm-message");
05156 } else {
05157 res = say_and_wait(chan, vms->newmessages, chan->language);
05158 res = res ? res : ast_play_and_wait(chan, "vm-nya");
05159 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05160 }
05161 if (!res && vms->oldmessages)
05162 res = ast_play_and_wait(chan, "vm-and");
05163 }
05164 if (!res && vms->oldmessages) {
05165 if (vms->oldmessages == 1) {
05166 res = ast_play_and_wait(chan, "digits/ett");
05167 res = res ? res : ast_play_and_wait(chan, "vm-gammalt");
05168 res = res ? res : ast_play_and_wait(chan, "vm-message");
05169 } else {
05170 res = say_and_wait(chan, vms->oldmessages, chan->language);
05171 res = res ? res : ast_play_and_wait(chan, "vm-gamla");
05172 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05173 }
05174 }
05175
05176 return res;
05177 }
05178
05179
05180 static int vm_intro_no(struct ast_channel *chan,struct vm_state *vms)
05181 {
05182
05183 int res;
05184
05185 res = ast_play_and_wait(chan, "vm-youhave");
05186 if (res)
05187 return res;
05188
05189 if (!vms->oldmessages && !vms->newmessages) {
05190 res = ast_play_and_wait(chan, "vm-no");
05191 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05192 return res;
05193 }
05194
05195 if (vms->newmessages) {
05196 if ((vms->newmessages == 1)) {
05197 res = ast_play_and_wait(chan, "digits/1");
05198 res = res ? res : ast_play_and_wait(chan, "vm-ny");
05199 res = res ? res : ast_play_and_wait(chan, "vm-message");
05200 } else {
05201 res = say_and_wait(chan, vms->newmessages, chan->language);
05202 res = res ? res : ast_play_and_wait(chan, "vm-nye");
05203 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05204 }
05205 if (!res && vms->oldmessages)
05206 res = ast_play_and_wait(chan, "vm-and");
05207 }
05208 if (!res && vms->oldmessages) {
05209 if (vms->oldmessages == 1) {
05210 res = ast_play_and_wait(chan, "digits/1");
05211 res = res ? res : ast_play_and_wait(chan, "vm-gamel");
05212 res = res ? res : ast_play_and_wait(chan, "vm-message");
05213 } else {
05214 res = say_and_wait(chan, vms->oldmessages, chan->language);
05215 res = res ? res : ast_play_and_wait(chan, "vm-gamle");
05216 res = res ? res : ast_play_and_wait(chan, "vm-messages");
05217 }
05218 }
05219
05220 return res;
05221 }
05222
05223
05224 static int vm_intro_de(struct ast_channel *chan,struct vm_state *vms)
05225 {
05226
05227 int res;
05228 res = ast_play_and_wait(chan, "vm-youhave");
05229 if (!res) {
05230 if (vms->newmessages) {
05231 if ((vms->newmessages == 1))
05232 res = ast_play_and_wait(chan, "digits/1F");
05233 else
05234 res = say_and_wait(chan, vms->newmessages, chan->language);
05235 if (!res)
05236 res = ast_play_and_wait(chan, "vm-INBOX");
05237 if (vms->oldmessages && !res)
05238 res = ast_play_and_wait(chan, "vm-and");
05239 else if (!res) {
05240 if ((vms->newmessages == 1))
05241 res = ast_play_and_wait(chan, "vm-message");
05242 else
05243 res = ast_play_and_wait(chan, "vm-messages");
05244 }
05245
05246 }
05247 if (!res && vms->oldmessages) {
05248 if (vms->oldmessages == 1)
05249 res = ast_play_and_wait(chan, "digits/1F");
05250 else
05251 res = say_and_wait(chan, vms->oldmessages, chan->language);
05252 if (!res)
05253 res = ast_play_and_wait(chan, "vm-Old");
05254 if (!res) {
05255 if (vms->oldmessages == 1)
05256 res = ast_play_and_wait(chan, "vm-message");
05257 else
05258 res = ast_play_and_wait(chan, "vm-messages");
05259 }
05260 }
05261 if (!res) {
05262 if (!vms->oldmessages && !vms->newmessages) {
05263 res = ast_play_and_wait(chan, "vm-no");
05264 if (!res)
05265 res = ast_play_and_wait(chan, "vm-messages");
05266 }
05267 }
05268 }
05269 return res;
05270 }
05271
05272
05273 static int vm_intro_es(struct ast_channel *chan,struct vm_state *vms)
05274 {
05275
05276 int res;
05277 if (!vms->oldmessages && !vms->newmessages) {
05278 res = ast_play_and_wait(chan, "vm-youhaveno");
05279 if (!res)
05280 res = ast_play_and_wait(chan, "vm-messages");
05281 } else {
05282 res = ast_play_and_wait(chan, "vm-youhave");
05283 }
05284 if (!res) {
05285 if (vms->newmessages) {
05286 if (!res) {
05287 if ((vms->newmessages == 1)) {
05288 res = ast_play_and_wait(chan, "digits/1M");
05289 if (!res)
05290 res = ast_play_and_wait(chan, "vm-message");
05291 if (!res)
05292 res = ast_play_and_wait(chan, "vm-INBOXs");
05293 } else {
05294 res = say_and_wait(chan, vms->newmessages, chan->language);
05295 if (!res)
05296 res = ast_play_and_wait(chan, "vm-messages");
05297 if (!res)
05298 res = ast_play_and_wait(chan, "vm-INBOX");
05299 }
05300 }
05301 if (vms->oldmessages && !res)
05302 res = ast_play_and_wait(chan, "vm-and");
05303 }
05304 if (vms->oldmessages) {
05305 if (!res) {
05306 if (vms->oldmessages == 1) {
05307 res = ast_play_and_wait(chan, "digits/1M");
05308 if (!res)
05309 res = ast_play_and_wait(chan, "vm-message");
05310 if (!res)
05311 res = ast_play_and_wait(chan, "vm-Olds");
05312 } else {
05313 res = say_and_wait(chan, vms->oldmessages, chan->language);
05314 if (!res)
05315 res = ast_play_and_wait(chan, "vm-messages");
05316 if (!res)
05317 res = ast_play_and_wait(chan, "vm-Old");
05318 }
05319 }
05320 }
05321 }
05322 return res;
05323 }
05324
05325
05326 static int vm_intro_pt_BR(struct ast_channel *chan,struct vm_state *vms) {
05327
05328 int res;
05329 if (!vms->oldmessages && !vms->newmessages) {
05330 res = ast_play_and_wait(chan, "vm-nomessages");
05331 return res;
05332 }
05333 else {
05334 res = ast_play_and_wait(chan, "vm-youhave");
05335 }
05336 if (vms->newmessages) {
05337 if (!res)
05338 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
05339 if ((vms->newmessages == 1)) {
05340 if (!res)
05341 res = ast_play_and_wait(chan, "vm-message");
05342 if (!res)
05343 res = ast_play_and_wait(chan, "vm-INBOXs");
05344 }
05345 else {
05346 if (!res)
05347 res = ast_play_and_wait(chan, "vm-messages");
05348 if (!res)
05349 res = ast_play_and_wait(chan, "vm-INBOX");
05350 }
05351 if (vms->oldmessages && !res)
05352 res = ast_play_and_wait(chan, "vm-and");
05353 }
05354 if (vms->oldmessages) {
05355 if (!res)
05356 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
05357 if (vms->oldmessages == 1) {
05358 if (!res)
05359 res = ast_play_and_wait(chan, "vm-message");
05360 if (!res)
05361 res = ast_play_and_wait(chan, "vm-Olds");
05362 }
05363 else {
05364 if (!res)
05365 res = ast_play_and_wait(chan, "vm-messages");
05366 if (!res)
05367 res = ast_play_and_wait(chan, "vm-Old");
05368 }
05369 }
05370 return res;
05371 }
05372
05373
05374 static int vm_intro_fr(struct ast_channel *chan,struct vm_state *vms)
05375 {
05376
05377 int res;
05378 res = ast_play_and_wait(chan, "vm-youhave");
05379 if (!res) {
05380 if (vms->newmessages) {
05381 res = say_and_wait(chan, vms->newmessages, chan->language);
05382 if (!res)
05383 res = ast_play_and_wait(chan, "vm-INBOX");
05384 if (vms->oldmessages && !res)
05385 res = ast_play_and_wait(chan, "vm-and");
05386 else if (!res) {
05387 if ((vms->newmessages == 1))
05388 res = ast_play_and_wait(chan, "vm-message");
05389 else
05390 res = ast_play_and_wait(chan, "vm-messages");
05391 }
05392
05393 }
05394 if (!res && vms->oldmessages) {
05395 res = say_and_wait(chan, vms->oldmessages, chan->language);
05396 if (!res)
05397 res = ast_play_and_wait(chan, "vm-Old");
05398 if (!res) {
05399 if (vms->oldmessages == 1)
05400 res = ast_play_and_wait(chan, "vm-message");
05401 else
05402 res = ast_play_and_wait(chan, "vm-messages");
05403 }
05404 }
05405 if (!res) {
05406 if (!vms->oldmessages && !vms->newmessages) {
05407 res = ast_play_and_wait(chan, "vm-no");
05408 if (!res)
05409 res = ast_play_and_wait(chan, "vm-messages");
05410 }
05411 }
05412 }
05413 return res;
05414 }
05415
05416
05417 static int vm_intro_nl(struct ast_channel *chan,struct vm_state *vms)
05418 {
05419
05420 int res;
05421 res = ast_play_and_wait(chan, "vm-youhave");
05422 if (!res) {
05423 if (vms->newmessages) {
05424 res = say_and_wait(chan, vms->newmessages, chan->language);
05425 if (!res) {
05426 if (vms->newmessages == 1)
05427 res = ast_play_and_wait(chan, "vm-INBOXs");
05428 else
05429 res = ast_play_and_wait(chan, "vm-INBOX");
05430 }
05431 if (vms->oldmessages && !res)
05432 res = ast_play_and_wait(chan, "vm-and");
05433 else if (!res) {
05434 if ((vms->newmessages == 1))
05435 res = ast_play_and_wait(chan, "vm-message");
05436 else
05437 res = ast_play_and_wait(chan, "vm-messages");
05438 }
05439
05440 }
05441 if (!res && vms->oldmessages) {
05442 res = say_and_wait(chan, vms->oldmessages, chan->language);
05443 if (!res) {
05444 if (vms->oldmessages == 1)
05445 res = ast_play_and_wait(chan, "vm-Olds");
05446 else
05447 res = ast_play_and_wait(chan, "vm-Old");
05448 }
05449 if (!res) {
05450 if (vms->oldmessages == 1)
05451 res = ast_play_and_wait(chan, "vm-message");
05452 else
05453 res = ast_play_and_wait(chan, "vm-messages");
05454 }
05455 }
05456 if (!res) {
05457 if (!vms->oldmessages && !vms->newmessages) {
05458 res = ast_play_and_wait(chan, "vm-no");
05459 if (!res)
05460 res = ast_play_and_wait(chan, "vm-messages");
05461 }
05462 }
05463 }
05464 return res;
05465 }
05466
05467
05468 static int vm_intro_pt(struct ast_channel *chan,struct vm_state *vms)
05469 {
05470
05471 int res;
05472 res = ast_play_and_wait(chan, "vm-youhave");
05473 if (!res) {
05474 if (vms->newmessages) {
05475 res = ast_say_number(chan, vms->newmessages, AST_DIGIT_ANY, chan->language, "f");
05476 if (!res) {
05477 if ((vms->newmessages == 1)) {
05478 res = ast_play_and_wait(chan, "vm-message");
05479 if (!res)
05480 res = ast_play_and_wait(chan, "vm-INBOXs");
05481 } else {
05482 res = ast_play_and_wait(chan, "vm-messages");
05483 if (!res)
05484 res = ast_play_and_wait(chan, "vm-INBOX");
05485 }
05486 }
05487 if (vms->oldmessages && !res)
05488 res = ast_play_and_wait(chan, "vm-and");
05489 }
05490 if (!res && vms->oldmessages) {
05491 res = ast_say_number(chan, vms->oldmessages, AST_DIGIT_ANY, chan->language, "f");
05492 if (!res) {
05493 if (vms->oldmessages == 1) {
05494 res = ast_play_and_wait(chan, "vm-message");
05495 if (!res)
05496 res = ast_play_and_wait(chan, "vm-Olds");
05497 } else {
05498 res = ast_play_and_wait(chan, "vm-messages");
05499 if (!res)
05500 res = ast_play_and_wait(chan, "vm-Old");
05501 }
05502 }
05503 }
05504 if (!res) {
05505 if (!vms->oldmessages && !vms->newmessages) {
05506 res = ast_play_and_wait(chan, "vm-no");
05507 if (!res)
05508 res = ast_play_and_wait(chan, "vm-messages");
05509 }
05510 }
05511 }
05512 return res;
05513 }
05514
05515
05516
05517
05518
05519
05520
05521
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531 static int vm_intro_cz(struct ast_channel *chan,struct vm_state *vms)
05532 {
05533 int res;
05534 res = ast_play_and_wait(chan, "vm-youhave");
05535 if (!res) {
05536 if (vms->newmessages) {
05537 if (vms->newmessages == 1) {
05538 res = ast_play_and_wait(chan, "digits/jednu");
05539 } else {
05540 res = say_and_wait(chan, vms->newmessages, chan->language);
05541 }
05542 if (!res) {
05543 if ((vms->newmessages == 1))
05544 res = ast_play_and_wait(chan, "vm-novou");
05545 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
05546 res = ast_play_and_wait(chan, "vm-nove");
05547 if (vms->newmessages > 4)
05548 res = ast_play_and_wait(chan, "vm-novych");
05549 }
05550 if (vms->oldmessages && !res)
05551 res = ast_play_and_wait(chan, "vm-and");
05552 else if (!res) {
05553 if ((vms->newmessages == 1))
05554 res = ast_play_and_wait(chan, "vm-zpravu");
05555 if ((vms->newmessages) > 1 && (vms->newmessages < 5))
05556 res = ast_play_and_wait(chan, "vm-zpravy");
05557 if (vms->newmessages > 4)
05558 res = ast_play_and_wait(chan, "vm-zprav");
05559 }
05560 }
05561 if (!res && vms->oldmessages) {
05562 res = say_and_wait(chan, vms->oldmessages, chan->language);
05563 if (!res) {
05564 if ((vms->oldmessages == 1))
05565 res = ast_play_and_wait(chan, "vm-starou");
05566 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
05567 res = ast_play_and_wait(chan, "vm-stare");
05568 if (vms->oldmessages > 4)
05569 res = ast_play_and_wait(chan, "vm-starych");
05570 }
05571 if (!res) {
05572 if ((vms->oldmessages == 1))
05573 res = ast_play_and_wait(chan, "vm-zpravu");
05574 if ((vms->oldmessages) > 1 && (vms->oldmessages < 5))
05575 res = ast_play_and_wait(chan, "vm-zpravy");
05576 if (vms->oldmessages > 4)
05577 res = ast_play_and_wait(chan, "vm-zprav");
05578 }
05579 }
05580 if (!res) {
05581 if (!vms->oldmessages && !vms->newmessages) {
05582 res = ast_play_and_wait(chan, "vm-no");
05583 if (!res)
05584 res = ast_play_and_wait(chan, "vm-zpravy");
05585 }
05586 }
05587 }
05588 return res;
05589 }
05590
05591 static int get_lastdigits(int num)
05592 {
05593 num %= 100;
05594 return (num < 20) ? num : num % 10;
05595 }
05596
05597 static int vm_intro_ru(struct ast_channel *chan,struct vm_state *vms)
05598 {
05599 int res;
05600 int lastnum = 0;
05601 int dcnum;
05602
05603 res = ast_play_and_wait(chan, "vm-youhave");
05604 if (!res && vms->newmessages) {
05605 lastnum = get_lastdigits(vms->newmessages);
05606 dcnum = vms->newmessages - lastnum;
05607 if (dcnum)
05608 res = say_and_wait(chan, dcnum, chan->language);
05609 if (!res && lastnum) {
05610 if (lastnum == 1)
05611 res = ast_play_and_wait(chan, "digits/ru/odno");
05612 else
05613 res = say_and_wait(chan, lastnum, chan->language);
05614 }
05615
05616 if (!res)
05617 res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-novoe" : "vm-novyh");
05618
05619 if (!res && vms->oldmessages)
05620 res = ast_play_and_wait(chan, "vm-and");
05621 }
05622
05623 if (!res && vms->oldmessages) {
05624 lastnum = get_lastdigits(vms->oldmessages);
05625 dcnum = vms->oldmessages - lastnum;
05626 if (dcnum)
05627 res = say_and_wait(chan, dcnum, chan->language);
05628 if (!res && lastnum) {
05629 if (lastnum == 1)
05630 res = ast_play_and_wait(chan, "digits/ru/odno");
05631 else
05632 res = say_and_wait(chan, lastnum, chan->language);
05633 }
05634
05635 if (!res)
05636 res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-staroe" : "vm-staryh");
05637 }
05638
05639 if (!res && !vms->newmessages && !vms->oldmessages) {
05640 lastnum = 0;
05641 res = ast_play_and_wait(chan, "vm-no");
05642 }
05643
05644 if (!res) {
05645 switch (lastnum) {
05646 case 1:
05647 res = ast_play_and_wait(chan, "vm-soobshenie");
05648 break;
05649 case 2:
05650 case 3:
05651 case 4:
05652 res = ast_play_and_wait(chan, "vm-soobsheniya");
05653 break;
05654 default:
05655 res = ast_play_and_wait(chan, "vm-soobsheniy");
05656 break;
05657 }
05658 }
05659
05660 return res;
05661 }
05662
05663
05664
05665
05666
05667
05668
05669
05670
05671 static int vm_intro_ua(struct ast_channel *chan,struct vm_state *vms)
05672 {
05673 int res;
05674 int lastnum = 0;
05675 int dcnum;
05676
05677 res = ast_play_and_wait(chan, "vm-youhave");
05678 if (!res && vms->newmessages) {
05679 lastnum = get_lastdigits(vms->newmessages);
05680 dcnum = vms->newmessages - lastnum;
05681 if (dcnum)
05682 res = say_and_wait(chan, dcnum, chan->language);
05683 if (!res && lastnum) {
05684 if (lastnum == 1)
05685 res = ast_play_and_wait(chan, "digits/ua/1e");
05686 else
05687 res = say_and_wait(chan, lastnum, chan->language);
05688 }
05689
05690 if (!res)
05691 res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-nove" : "vm-INBOX");
05692
05693 if (!res && vms->oldmessages)
05694 res = ast_play_and_wait(chan, "vm-and");
05695 }
05696
05697 if (!res && vms->oldmessages) {
05698 lastnum = get_lastdigits(vms->oldmessages);
05699 dcnum = vms->oldmessages - lastnum;
05700 if (dcnum)
05701 res = say_and_wait(chan, dcnum, chan->language);
05702 if (!res && lastnum) {
05703 if (lastnum == 1)
05704 res = ast_play_and_wait(chan, "digits/ua/1e");
05705 else
05706 res = say_and_wait(chan, lastnum, chan->language);
05707 }
05708
05709 if (!res)
05710 res = ast_play_and_wait(chan, (lastnum == 1) ? "vm-stare" : "vm-Old");
05711 }
05712
05713 if (!res && !vms->newmessages && !vms->oldmessages) {
05714 lastnum = 0;
05715 res = ast_play_and_wait(chan, "vm-no");
05716 }
05717
05718 if (!res) {
05719 switch (lastnum) {
05720 case 1:
05721 case 2:
05722 case 3:
05723 case 4:
05724 res = ast_play_and_wait(chan, "vm-message");
05725 break;
05726 default:
05727 res = ast_play_and_wait(chan, "vm-messages");
05728 break;
05729 }
05730 }
05731
05732 return res;
05733 }
05734
05735
05736 static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms)
05737 {
05738 char prefile[256];
05739
05740
05741 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
05742 if (ast_test_flag(vmu, VM_TEMPGREETWARN)) {
05743 if (ast_fileexists(prefile, NULL, NULL) > 0)
05744 ast_play_and_wait(chan, "vm-tempgreetactive");
05745 }
05746
05747
05748 if (!strcasecmp(chan->language, "de")) {
05749 return vm_intro_de(chan, vms);
05750 } else if (!strcasecmp(chan->language, "es")) {
05751 return vm_intro_es(chan, vms);
05752 } else if (!strcasecmp(chan->language, "it")) {
05753 return vm_intro_it(chan, vms);
05754 } else if (!strcasecmp(chan->language, "fr")) {
05755 return vm_intro_fr(chan, vms);
05756 } else if (!strcasecmp(chan->language, "nl")) {
05757 return vm_intro_nl(chan, vms);
05758 } else if (!strcasecmp(chan->language, "pt")) {
05759 return vm_intro_pt(chan, vms);
05760 } else if (!strcasecmp(chan->language, "pt_BR")) {
05761 return vm_intro_pt_BR(chan, vms);
05762 } else if (!strcasecmp(chan->language, "cz")) {
05763 return vm_intro_cz(chan, vms);
05764 } else if (!strcasecmp(chan->language, "gr")) {
05765 return vm_intro_gr(chan, vms);
05766 } else if (!strcasecmp(chan->language, "pl")) {
05767 return vm_intro_pl(chan, vms);
05768 } else if (!strcasecmp(chan->language, "se")) {
05769 return vm_intro_se(chan, vms);
05770 } else if (!strcasecmp(chan->language, "no")) {
05771 return vm_intro_no(chan, vms);
05772 } else if (!strcasecmp(chan->language, "ru")) {
05773 return vm_intro_ru(chan, vms);
05774 } else if (!strcasecmp(chan->language, "ua")) {
05775 return vm_intro_ua(chan, vms);
05776 } else {
05777 return vm_intro_en(chan, vms);
05778 }
05779 }
05780
05781 static int vm_instructions(struct ast_channel *chan, struct vm_state *vms, int skipadvanced)
05782 {
05783 int res = 0;
05784
05785 while (!res) {
05786 if (vms->starting) {
05787 if (vms->lastmsg > -1) {
05788 res = ast_play_and_wait(chan, "vm-onefor");
05789 if (!res)
05790 res = vm_play_folder_name(chan, vms->vmbox);
05791 }
05792 if (!res)
05793 res = ast_play_and_wait(chan, "vm-opts");
05794 } else {
05795 if (vms->curmsg)
05796 res = ast_play_and_wait(chan, "vm-prev");
05797 if (!res && !skipadvanced)
05798 res = ast_play_and_wait(chan, "vm-advopts");
05799 if (!res)
05800 res = ast_play_and_wait(chan, "vm-repeat");
05801 if (!res && (vms->curmsg != vms->lastmsg))
05802 res = ast_play_and_wait(chan, "vm-next");
05803 if (!res) {
05804 if (!vms->deleted[vms->curmsg])
05805 res = ast_play_and_wait(chan, "vm-delete");
05806 else
05807 res = ast_play_and_wait(chan, "vm-undelete");
05808 if (!res)
05809 res = ast_play_and_wait(chan, "vm-toforward");
05810 if (!res)
05811 res = ast_play_and_wait(chan, "vm-savemessage");
05812 }
05813 }
05814 if (!res)
05815 res = ast_play_and_wait(chan, "vm-helpexit");
05816 if (!res)
05817 res = ast_waitfordigit(chan, 6000);
05818 if (!res) {
05819 vms->repeats++;
05820 if (vms->repeats > 2) {
05821 res = 't';
05822 }
05823 }
05824 }
05825 return res;
05826 }
05827
05828 static int vm_newuser(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
05829 {
05830 int cmd = 0;
05831 int duration = 0;
05832 int tries = 0;
05833 char newpassword[80] = "";
05834 char newpassword2[80] = "";
05835 char prefile[PATH_MAX] = "";
05836 unsigned char buf[256];
05837 int bytes=0;
05838
05839 if (ast_adsi_available(chan)) {
05840 bytes += adsi_logo(buf + bytes);
05841 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "New User Setup", "");
05842 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
05843 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05844 bytes += ast_adsi_voice_mode(buf + bytes, 0);
05845 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05846 }
05847
05848
05849
05850 for (;;) {
05851 newpassword[1] = '\0';
05852 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
05853 if (cmd == '#')
05854 newpassword[0] = '\0';
05855 if (cmd < 0 || cmd == 't' || cmd == '#')
05856 return cmd;
05857 cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#");
05858 if (cmd < 0 || cmd == 't' || cmd == '#')
05859 return cmd;
05860 newpassword2[1] = '\0';
05861 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
05862 if (cmd == '#')
05863 newpassword2[0] = '\0';
05864 if (cmd < 0 || cmd == 't' || cmd == '#')
05865 return cmd;
05866 cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#");
05867 if (cmd < 0 || cmd == 't' || cmd == '#')
05868 return cmd;
05869 if (!strcmp(newpassword, newpassword2))
05870 break;
05871 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
05872 cmd = ast_play_and_wait(chan, "vm-mismatch");
05873 if (++tries == 3)
05874 return -1;
05875 }
05876 if (ast_strlen_zero(ext_pass_cmd))
05877 vm_change_password(vmu,newpassword);
05878 else
05879 vm_change_password_shell(vmu,newpassword);
05880 if (option_debug > 2)
05881 ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
05882 cmd = ast_play_and_wait(chan,"vm-passchanged");
05883
05884
05885 if (ast_test_flag(vmu, VM_FORCENAME)) {
05886 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
05887 if (ast_fileexists(prefile, NULL, NULL) < 1) {
05888 #ifndef IMAP_STORAGE
05889 cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05890 #else
05891 cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05892 #endif
05893 if (cmd < 0 || cmd == 't' || cmd == '#')
05894 return cmd;
05895 }
05896 }
05897
05898
05899 if (ast_test_flag(vmu, VM_FORCEGREET)) {
05900 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
05901 if (ast_fileexists(prefile, NULL, NULL) < 1) {
05902 #ifndef IMAP_STORAGE
05903 cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05904 #else
05905 cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05906 #endif
05907 if (cmd < 0 || cmd == 't' || cmd == '#')
05908 return cmd;
05909 }
05910
05911 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
05912 if (ast_fileexists(prefile, NULL, NULL) < 1) {
05913 #ifndef IMAP_STORAGE
05914 cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05915 #else
05916 cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05917 #endif
05918 if (cmd < 0 || cmd == 't' || cmd == '#')
05919 return cmd;
05920 }
05921 }
05922
05923 return cmd;
05924 }
05925
05926 static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
05927 {
05928 int cmd = 0;
05929 int retries = 0;
05930 int duration = 0;
05931 char newpassword[80] = "";
05932 char newpassword2[80] = "";
05933 char prefile[PATH_MAX] = "";
05934 unsigned char buf[256];
05935 int bytes=0;
05936
05937 if (ast_adsi_available(chan))
05938 {
05939 bytes += adsi_logo(buf + bytes);
05940 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
05941 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
05942 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
05943 bytes += ast_adsi_voice_mode(buf + bytes, 0);
05944 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
05945 }
05946 while ((cmd >= 0) && (cmd != 't')) {
05947 if (cmd)
05948 retries = 0;
05949 switch (cmd) {
05950 case '1':
05951 snprintf(prefile,sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username);
05952 #ifndef IMAP_STORAGE
05953 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05954 #else
05955 cmd = play_record_review(chan,"vm-rec-unv",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05956 #endif
05957 break;
05958 case '2':
05959 snprintf(prefile,sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username);
05960 #ifndef IMAP_STORAGE
05961 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05962 #else
05963 cmd = play_record_review(chan,"vm-rec-busy",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05964 #endif
05965 break;
05966 case '3':
05967 snprintf(prefile,sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username);
05968 #ifndef IMAP_STORAGE
05969 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
05970 #else
05971 cmd = play_record_review(chan,"vm-rec-name",prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
05972 #endif
05973 break;
05974 case '4':
05975 cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain);
05976 break;
05977 case '5':
05978 if (vmu->password[0] == '-') {
05979 cmd = ast_play_and_wait(chan, "vm-no");
05980 break;
05981 }
05982 newpassword[1] = '\0';
05983 newpassword[0] = cmd = ast_play_and_wait(chan,"vm-newpassword");
05984 if (cmd == '#')
05985 newpassword[0] = '\0';
05986 else {
05987 if (cmd < 0)
05988 break;
05989 if ((cmd = ast_readstring(chan,newpassword + strlen(newpassword),sizeof(newpassword)-1,2000,10000,"#")) < 0) {
05990 break;
05991 }
05992 }
05993 newpassword2[1] = '\0';
05994 newpassword2[0] = cmd = ast_play_and_wait(chan,"vm-reenterpassword");
05995 if (cmd == '#')
05996 newpassword2[0] = '\0';
05997 else {
05998 if (cmd < 0)
05999 break;
06000
06001 if ((cmd = ast_readstring(chan,newpassword2 + strlen(newpassword2),sizeof(newpassword2)-1,2000,10000,"#"))) {
06002 break;
06003 }
06004 }
06005 if (strcmp(newpassword, newpassword2)) {
06006 ast_log(LOG_NOTICE,"Password mismatch for user %s (%s != %s)\n", vms->username, newpassword, newpassword2);
06007 cmd = ast_play_and_wait(chan, "vm-mismatch");
06008 break;
06009 }
06010 if (ast_strlen_zero(ext_pass_cmd))
06011 vm_change_password(vmu,newpassword);
06012 else
06013 vm_change_password_shell(vmu,newpassword);
06014 if (option_debug > 2)
06015 ast_log(LOG_DEBUG,"User %s set password to %s of length %d\n",vms->username,newpassword,(int)strlen(newpassword));
06016 cmd = ast_play_and_wait(chan,"vm-passchanged");
06017 break;
06018 case '*':
06019 cmd = 't';
06020 break;
06021 default:
06022 cmd = ast_play_and_wait(chan,"vm-options");
06023 if (!cmd)
06024 cmd = ast_waitfordigit(chan,6000);
06025 if (!cmd)
06026 retries++;
06027 if (retries > 3)
06028 cmd = 't';
06029 }
06030 }
06031 if (cmd == 't')
06032 cmd = 0;
06033 return cmd;
06034 }
06035
06036 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
06037 {
06038 int res;
06039 int cmd = 0;
06040 int retries = 0;
06041 int duration = 0;
06042 char prefile[PATH_MAX] = "";
06043 unsigned char buf[256];
06044 char dest[PATH_MAX];
06045 int bytes = 0;
06046
06047 if (ast_adsi_available(chan)) {
06048 bytes += adsi_logo(buf + bytes);
06049 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Temp Greeting Menu", "");
06050 bytes += ast_adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
06051 bytes += ast_adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
06052 bytes += ast_adsi_voice_mode(buf + bytes, 0);
06053 ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
06054 }
06055
06056 snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username);
06057 if ((res = create_dirpath(dest, sizeof(dest), vmu->context, vms->username, "temp"))) {
06058 ast_log(LOG_WARNING, "Failed to create directory (%s).\n", prefile);
06059 return -1;
06060 }
06061 while((cmd >= 0) && (cmd != 't')) {
06062 if (cmd)
06063 retries = 0;
06064 RETRIEVE(prefile, -1);
06065 if (ast_fileexists(prefile, NULL, NULL) <= 0) {
06066 #ifndef IMAP_STORAGE
06067 play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
06068 #else
06069 play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
06070 #endif
06071 cmd = 't';
06072 } else {
06073 switch (cmd) {
06074 case '1':
06075 #ifndef IMAP_STORAGE
06076 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, NULL);
06077 #else
06078 cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, record_gain, vms);
06079 #endif
06080 break;
06081 case '2':
06082 DELETE(prefile, -1, prefile);
06083 ast_play_and_wait(chan, "vm-tempremoved");
06084 cmd = 't';
06085 break;
06086 case '*':
06087 cmd = 't';
06088 break;
06089 default:
06090 cmd = ast_play_and_wait(chan,
06091 ast_fileexists(prefile, NULL, NULL) > 0 ?
06092 "vm-tempgreeting2" : "vm-tempgreeting");
06093 if (!cmd)
06094 cmd = ast_waitfordigit(chan,6000);
06095 if (!cmd)
06096 retries++;
06097 if (retries > 3)
06098 cmd = 't';
06099 }
06100 }
06101 DISPOSE(prefile, -1);
06102 }
06103 if (cmd == 't')
06104 cmd = 0;
06105 return cmd;
06106 }
06107
06108
06109
06110 static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06111 {
06112 int cmd=0;
06113
06114 if (vms->lastmsg > -1) {
06115 cmd = play_message(chan, vmu, vms);
06116 } else {
06117 cmd = ast_play_and_wait(chan, "vm-youhaveno");
06118 if (!strcasecmp(vms->vmbox, "vm-INBOX") ||!strcasecmp(vms->vmbox, "vm-Old")){
06119 if (!cmd) {
06120 snprintf(vms->fn, sizeof(vms->fn), "vm-%ss", vms->curbox);
06121 cmd = ast_play_and_wait(chan, vms->fn);
06122 }
06123 if (!cmd)
06124 cmd = ast_play_and_wait(chan, "vm-messages");
06125 } else {
06126 if (!cmd)
06127 cmd = ast_play_and_wait(chan, "vm-messages");
06128 if (!cmd) {
06129 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
06130 cmd = ast_play_and_wait(chan, vms->fn);
06131 }
06132 }
06133 }
06134 return cmd;
06135 }
06136
06137
06138 static int vm_browse_messages_en(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06139 {
06140 int cmd=0;
06141
06142 if (vms->lastmsg > -1) {
06143 cmd = play_message(chan, vmu, vms);
06144 } else {
06145 cmd = ast_play_and_wait(chan, "vm-youhave");
06146 if (!cmd)
06147 cmd = ast_play_and_wait(chan, "vm-no");
06148 if (!cmd) {
06149 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
06150 cmd = ast_play_and_wait(chan, vms->fn);
06151 }
06152 if (!cmd)
06153 cmd = ast_play_and_wait(chan, "vm-messages");
06154 }
06155 return cmd;
06156 }
06157
06158
06159 static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06160 {
06161 int cmd=0;
06162
06163 if (vms->lastmsg > -1) {
06164 cmd = play_message(chan, vmu, vms);
06165 } else {
06166 cmd = ast_play_and_wait(chan, "vm-no");
06167 if (!cmd)
06168 cmd = ast_play_and_wait(chan, "vm-message");
06169 if (!cmd) {
06170 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
06171 cmd = ast_play_and_wait(chan, vms->fn);
06172 }
06173 }
06174 return cmd;
06175 }
06176
06177
06178 static int vm_browse_messages_es(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06179 {
06180 int cmd=0;
06181
06182 if (vms->lastmsg > -1) {
06183 cmd = play_message(chan, vmu, vms);
06184 } else {
06185 cmd = ast_play_and_wait(chan, "vm-youhaveno");
06186 if (!cmd)
06187 cmd = ast_play_and_wait(chan, "vm-messages");
06188 if (!cmd) {
06189 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
06190 cmd = ast_play_and_wait(chan, vms->fn);
06191 }
06192 }
06193 return cmd;
06194 }
06195
06196
06197 static int vm_browse_messages_pt(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06198 {
06199 int cmd=0;
06200
06201 if (vms->lastmsg > -1) {
06202 cmd = play_message(chan, vmu, vms);
06203 } else {
06204 cmd = ast_play_and_wait(chan, "vm-no");
06205 if (!cmd) {
06206 snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
06207 cmd = ast_play_and_wait(chan, vms->fn);
06208 }
06209 if (!cmd)
06210 cmd = ast_play_and_wait(chan, "vm-messages");
06211 }
06212 return cmd;
06213 }
06214
06215 static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
06216 {
06217 if (!strcasecmp(chan->language, "es")) {
06218 return vm_browse_messages_es(chan, vms, vmu);
06219 } else if (!strcasecmp(chan->language, "it")) {
06220 return vm_browse_messages_it(chan, vms, vmu);
06221 } else if (!strcasecmp(chan->language, "pt") || !strcasecmp(chan->language, "pt_BR")) {
06222 return vm_browse_messages_pt(chan, vms, vmu);
06223 } else if (!strcasecmp(chan->language, "gr")){
06224 return vm_browse_messages_gr(chan, vms, vmu);
06225 } else {
06226 return vm_browse_messages_en(chan, vms, vmu);
06227 }
06228 }
06229
06230 static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_size,
06231 struct ast_vm_user *res_vmu, const char *context, const char *prefix,
06232 int skipuser, int maxlogins, int silent)
06233 {
06234 int useadsi=0, valid=0, logretries=0;
06235 char password[AST_MAX_EXTENSION]="", *passptr;
06236 struct ast_vm_user vmus, *vmu = NULL;
06237
06238
06239 adsi_begin(chan, &useadsi);
06240 if (!skipuser && useadsi)
06241 adsi_login(chan);
06242 if (!silent && !skipuser && ast_streamfile(chan, "vm-login", chan->language)) {
06243 ast_log(LOG_WARNING, "Couldn't stream login file\n");
06244 return -1;
06245 }
06246
06247
06248
06249 while (!valid && (logretries < maxlogins)) {
06250
06251 if (!skipuser && ast_readstring(chan, mailbox, mailbox_size - 1, 2000, 10000, "#") < 0) {
06252 ast_log(LOG_WARNING, "Couldn't read username\n");
06253 return -1;
06254 }
06255 if (ast_strlen_zero(mailbox)) {
06256 if (chan->cid.cid_num) {
06257 ast_copy_string(mailbox, chan->cid.cid_num, mailbox_size);
06258 } else {
06259 if (option_verbose > 2)
06260 ast_verbose(VERBOSE_PREFIX_3 "Username not entered\n");
06261 return -1;
06262 }
06263 }
06264 if (useadsi)
06265 adsi_password(chan);
06266
06267 if (!ast_strlen_zero(prefix)) {
06268 char fullusername[80] = "";
06269 ast_copy_string(fullusername, prefix, sizeof(fullusername));
06270 strncat(fullusername, mailbox, sizeof(fullusername) - 1 - strlen(fullusername));
06271 ast_copy_string(mailbox, fullusername, mailbox_size);
06272 }
06273
06274 if (option_debug)
06275 ast_log(LOG_DEBUG, "Before find user for mailbox %s\n",mailbox);
06276 vmu = find_user(&vmus, context, mailbox);
06277 if (vmu && (vmu->password[0] == '\0' || (vmu->password[0] == '-' && vmu->password[1] == '\0'))) {
06278
06279 password[0] = '\0';
06280 } else {
06281 if (ast_streamfile(chan, "vm-password", chan->language)) {
06282 ast_log(LOG_WARNING, "Unable to stream password file\n");
06283 return -1;
06284 }
06285 if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
06286 ast_log(LOG_WARNING, "Unable to read password\n");
06287 return -1;
06288 }
06289 }
06290
06291 if (vmu) {
06292 passptr = vmu->password;
06293 if (passptr[0] == '-') passptr++;
06294 }
06295 if (vmu && !strcmp(passptr, password))
06296 valid++;
06297 else {
06298 if (option_verbose > 2)
06299 ast_verbose( VERBOSE_PREFIX_3 "Incorrect password '%s' for user '%s' (context = %s)\n", password, mailbox, context ? context : "default");
06300 if (!ast_strlen_zero(prefix))
06301 mailbox[0] = '\0';
06302 }
06303 logretries++;
06304 if (!valid) {
06305 if (skipuser || logretries >= maxlogins) {
06306 if (ast_streamfile(chan, "vm-incorrect", chan->language)) {
06307 ast_log(LOG_WARNING, "Unable to stream incorrect message\n");
06308 return -1;
06309 }
06310 } else {
06311 if (useadsi)
06312 adsi_login(chan);
06313 if (ast_streamfile(chan, "vm-incorrect-mailbox", chan->language)) {
06314 ast_log(LOG_WARNING, "Unable to stream incorrect mailbox message\n");
06315 return -1;
06316 }
06317 }
06318 if (ast_waitstream(chan, ""))
06319 return -1;
06320 }
06321 }
06322 if (!valid && (logretries >= maxlogins)) {
06323 ast_stopstream(chan);
06324 ast_play_and_wait(chan, "vm-goodbye");
06325 return -1;
06326 }
06327 if (vmu && !skipuser) {
06328 memcpy(res_vmu, vmu, sizeof(struct ast_vm_user));
06329 }
06330 return 0;
06331 }
06332
06333 static int vm_execmain(struct ast_channel *chan, void *data)
06334 {
06335
06336
06337
06338 int res=-1;
06339 int cmd=0;
06340 int valid = 0;
06341 struct ast_module_user *u;
06342 char prefixstr[80] ="";
06343 char ext_context[256]="";
06344 int box;
06345 int useadsi = 0;
06346 int skipuser = 0;
06347 struct vm_state vms;
06348 struct ast_vm_user *vmu = NULL, vmus;
06349 char *context=NULL;
06350 int silentexit = 0;
06351 struct ast_flags flags = { 0 };
06352 signed char record_gain = 0;
06353 int play_auto = 0;
06354 int play_folder = 0;
06355 #ifdef IMAP_STORAGE
06356 int deleted = 0;
06357 #endif
06358 u = ast_module_user_add(chan);
06359
06360
06361 memset(&vms, 0, sizeof(vms));
06362 vms.lastmsg = -1;
06363
06364 memset(&vmus, 0, sizeof(vmus));
06365
06366 if (chan->_state != AST_STATE_UP) {
06367 if (option_debug)
06368 ast_log(LOG_DEBUG, "Before ast_answer\n");
06369 ast_answer(chan);
06370 }
06371
06372 if (!ast_strlen_zero(data)) {
06373 char *opts[OPT_ARG_ARRAY_SIZE];
06374 char *parse;
06375 AST_DECLARE_APP_ARGS(args,
06376 AST_APP_ARG(argv0);
06377 AST_APP_ARG(argv1);
06378 );
06379
06380 parse = ast_strdupa(data);
06381
06382 AST_STANDARD_APP_ARGS(args, parse);
06383
06384 if (args.argc == 2) {
06385 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
06386 ast_module_user_remove(u);
06387 return -1;
06388 }
06389 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
06390 int gain;
06391 if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) {
06392 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
06393 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
06394 ast_module_user_remove(u);
06395 return -1;
06396 } else {
06397 record_gain = (signed char) gain;
06398 }
06399 } else {
06400 ast_log(LOG_WARNING, "Invalid Gain level set with option g\n");
06401 }
06402 }
06403 if (ast_test_flag(&flags, OPT_AUTOPLAY) ) {
06404 play_auto = 1;
06405 if (opts[OPT_ARG_PLAYFOLDER]) {
06406 if (sscanf(opts[OPT_ARG_PLAYFOLDER], "%d", &play_folder) != 1) {
06407 ast_log(LOG_WARNING, "Invalid value '%s' provided for folder autoplay option\n", opts[OPT_ARG_PLAYFOLDER]);
06408 }
06409 } else {
06410 ast_log(LOG_WARNING, "Invalid folder set with option a\n");
06411 }
06412 if ( play_folder > 9 || play_folder < 0) {
06413 ast_log(LOG_WARNING, "Invalid value '%d' provided for folder autoplay option\n", play_folder);
06414 play_folder = 0;
06415 }
06416 }
06417 } else {
06418
06419 while (*(args.argv0)) {
06420 if (*(args.argv0) == 's')
06421 ast_set_flag(&flags, OPT_SILENT);
06422 else if (*(args.argv0) == 'p')
06423 ast_set_flag(&flags, OPT_PREPEND_MAILBOX);
06424 else
06425 break;
06426 (args.argv0)++;
06427 }
06428
06429 }
06430
06431 valid = ast_test_flag(&flags, OPT_SILENT);
06432
06433 if ((context = strchr(args.argv0, '@')))
06434 *context++ = '\0';
06435
06436 if (ast_test_flag(&flags, OPT_PREPEND_MAILBOX))
06437 ast_copy_string(prefixstr, args.argv0, sizeof(prefixstr));
06438 else
06439 ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
06440
06441 if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
06442 skipuser++;
06443 else
06444 valid = 0;
06445 }
06446
06447 if (!valid)
06448 res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0);
06449
06450 if (option_debug)
06451 ast_log(LOG_DEBUG, "After vm_authenticate\n");
06452 if (!res) {
06453 valid = 1;
06454 if (!skipuser)
06455 vmu = &vmus;
06456 } else {
06457 res = 0;
06458 }
06459
06460
06461 adsi_begin(chan, &useadsi);
06462
06463 #ifdef IMAP_STORAGE
06464 vms.interactive = 1;
06465 vms.updated = 1;
06466 vmstate_insert(&vms);
06467 init_vm_state(&vms);
06468 #endif
06469 if (!valid)
06470 goto out;
06471
06472 if (!(vms.deleted = ast_calloc(vmu->maxmsg, sizeof(int)))) {
06473
06474 }
06475 if (!(vms.heard = ast_calloc(vmu->maxmsg, sizeof(int)))) {
06476
06477 }
06478
06479
06480 if (!ast_strlen_zero(vmu->language))
06481 ast_string_field_set(chan, language, vmu->language);
06482 #ifndef IMAP_STORAGE
06483 create_dirpath(vms.curdir, sizeof(vms.curdir), vmu->context, vms.username, "");
06484 #endif
06485
06486 if (option_debug)
06487 ast_log(LOG_DEBUG, "Before open_mailbox\n");
06488 res = open_mailbox(&vms, vmu, 1);
06489 if (res == ERROR_LOCK_PATH)
06490 goto out;
06491 vms.oldmessages = vms.lastmsg + 1;
06492 if (option_debug > 2)
06493 ast_log(LOG_DEBUG, "Number of old messages: %d\n",vms.oldmessages);
06494
06495 res = open_mailbox(&vms, vmu, 0);
06496 if (res == ERROR_LOCK_PATH)
06497 goto out;
06498 vms.newmessages = vms.lastmsg + 1;
06499 if (option_debug > 2)
06500 ast_log(LOG_DEBUG, "Number of new messages: %d\n",vms.newmessages);
06501
06502
06503 if (play_auto) {
06504 res = open_mailbox(&vms, vmu, play_folder);
06505 if (res == ERROR_LOCK_PATH)
06506 goto out;
06507
06508
06509 if (vms.lastmsg == -1) {
06510 cmd = vm_browse_messages(chan, &vms, vmu);
06511 res = 0;
06512 goto out;
06513 }
06514 } else {
06515 if (!vms.newmessages && vms.oldmessages) {
06516
06517 res = open_mailbox(&vms, vmu, 1);
06518 play_folder = 1;
06519 if (res == ERROR_LOCK_PATH)
06520 goto out;
06521 }
06522 }
06523
06524 if (useadsi)
06525 adsi_status(chan, &vms);
06526 res = 0;
06527
06528
06529 if (!strcasecmp(vmu->mailbox, vmu->password) &&
06530 (ast_test_flag(vmu, VM_FORCENAME | VM_FORCEGREET))) {
06531 if (ast_play_and_wait(chan, "vm-newuser") == -1)
06532 ast_log(LOG_WARNING, "Couldn't stream new user file\n");
06533 cmd = vm_newuser(chan, vmu, &vms, vmfmts, record_gain);
06534 if ((cmd == 't') || (cmd == '#')) {
06535
06536 res = 0;
06537 goto out;
06538 } else if (cmd < 0) {
06539
06540 res = -1;
06541 goto out;
06542 }
06543 }
06544 #ifdef IMAP_STORAGE
06545 if(option_debug > 2)
06546 ast_log(LOG_DEBUG, "Checking quotas: comparing %u to %u\n",vms.quota_usage,vms.quota_limit);
06547 if (vms.quota_limit && vms.quota_usage >= vms.quota_limit) {
06548 if (option_debug)
06549 ast_log(LOG_DEBUG, "*** QUOTA EXCEEDED!!\n");
06550 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
06551 }
06552 #endif
06553 if (play_auto) {
06554 cmd = '1';
06555 } else {
06556 cmd = vm_intro(chan, vmu, &vms);
06557 }
06558
06559 vms.repeats = 0;
06560 vms.starting = 1;
06561 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
06562
06563 switch (cmd) {
06564 case '1':
06565 vms.curmsg = 0;
06566
06567 case '5':
06568 cmd = vm_browse_messages(chan, &vms, vmu);
06569 break;
06570 case '2':
06571 if (useadsi)
06572 adsi_folders(chan, 0, "Change to folder...");
06573 cmd = get_folder2(chan, "vm-changeto", 0);
06574 if (cmd == '#') {
06575 cmd = 0;
06576 } else if (cmd > 0) {
06577 cmd = cmd - '0';
06578 res = close_mailbox(&vms, vmu);
06579 if (res == ERROR_LOCK_PATH)
06580 goto out;
06581 res = open_mailbox(&vms, vmu, cmd);
06582 if (res == ERROR_LOCK_PATH)
06583 goto out;
06584 play_folder = cmd;
06585 cmd = 0;
06586 }
06587 if (useadsi)
06588 adsi_status2(chan, &vms);
06589
06590 if (!cmd)
06591 cmd = vm_play_folder_name(chan, vms.vmbox);
06592
06593 vms.starting = 1;
06594 break;
06595 case '3':
06596 cmd = 0;
06597 vms.repeats = 0;
06598 while ((cmd > -1) && (cmd != 't') && (cmd != '#')) {
06599 switch (cmd) {
06600 case '1':
06601 if (vms.lastmsg > -1 && !vms.starting) {
06602 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain);
06603 if (cmd == ERROR_LOCK_PATH) {
06604 res = cmd;
06605 goto out;
06606 }
06607 } else
06608 cmd = ast_play_and_wait(chan, "vm-sorry");
06609 cmd = 't';
06610 break;
06611 case '2':
06612 if (option_verbose > 2 && !vms.starting)
06613 ast_verbose( VERBOSE_PREFIX_3 "Callback Requested\n");
06614 if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) {
06615 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain);
06616 if (cmd == 9) {
06617 silentexit = 1;
06618 goto out;
06619 } else if (cmd == ERROR_LOCK_PATH) {
06620 res = cmd;
06621 goto out;
06622 }
06623 }
06624 else
06625 cmd = ast_play_and_wait(chan, "vm-sorry");
06626 cmd = 't';
06627 break;
06628 case '3':
06629 if (vms.lastmsg > -1 && !vms.starting) {
06630 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain);
06631 if (cmd == ERROR_LOCK_PATH) {
06632 res = cmd;
06633 goto out;
06634 }
06635 } else
06636 cmd = ast_play_and_wait(chan, "vm-sorry");
06637 cmd = 't';
06638 break;
06639 case '4':
06640 if (!ast_strlen_zero(vmu->dialout)) {
06641 cmd = dialout(chan, vmu, NULL, vmu->dialout);
06642 if (cmd == 9) {
06643 silentexit = 1;
06644 goto out;
06645 }
06646 }
06647 else
06648 cmd = ast_play_and_wait(chan, "vm-sorry");
06649 cmd = 't';
06650 break;
06651
06652 case '5':
06653 if (ast_test_flag(vmu, VM_SVMAIL)) {
06654 cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain);
06655 if (cmd == ERROR_LOCK_PATH) {
06656 res = cmd;
06657 ast_log(LOG_WARNING, "forward_message failed to lock path.\n");
06658 goto out;
06659 }
06660 } else
06661 cmd = ast_play_and_wait(chan,"vm-sorry");
06662 cmd='t';
06663 break;
06664
06665 case '*':
06666 cmd = 't';
06667 break;
06668
06669 default:
06670 cmd = 0;
06671 if (!vms.starting) {
06672 cmd = ast_play_and_wait(chan, "vm-toreply");
06673 }
06674 if (!ast_strlen_zero(vmu->callback) && !vms.starting && !cmd) {
06675 cmd = ast_play_and_wait(chan, "vm-tocallback");
06676 }
06677 if (!cmd && !vms.starting) {
06678 cmd = ast_play_and_wait(chan, "vm-tohearenv");
06679 }
06680 if (!ast_strlen_zero(vmu->dialout) && !cmd) {
06681 cmd = ast_play_and_wait(chan, "vm-tomakecall");
06682 }
06683 if (ast_test_flag(vmu, VM_SVMAIL) && !cmd)
06684 cmd=ast_play_and_wait(chan, "vm-leavemsg");
06685 if (!cmd)
06686 cmd = ast_play_and_wait(chan, "vm-starmain");
06687 if (!cmd)
06688 cmd = ast_waitfordigit(chan,6000);
06689 if (!cmd)
06690 vms.repeats++;
06691 if (vms.repeats > 3)
06692 cmd = 't';
06693 }
06694 }
06695 if (cmd == 't') {
06696 cmd = 0;
06697 vms.repeats = 0;
06698 }
06699 break;
06700 case '4':
06701 if (vms.curmsg > 0) {
06702 vms.curmsg--;
06703 cmd = play_message(chan, vmu, &vms);
06704 } else {
06705 cmd = ast_play_and_wait(chan, "vm-nomore");
06706 }
06707 break;
06708 case '6':
06709 if (vms.curmsg < vms.lastmsg) {
06710 vms.curmsg++;
06711 cmd = play_message(chan, vmu, &vms);
06712 } else {
06713 cmd = ast_play_and_wait(chan, "vm-nomore");
06714 }
06715 break;
06716 case '7':
06717 if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
06718 vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
06719 if (useadsi)
06720 adsi_delete(chan, &vms);
06721 if (vms.deleted[vms.curmsg]) {
06722 if (play_folder == 0)
06723 vms.newmessages--;
06724 else if (play_folder == 1)
06725 vms.oldmessages--;
06726 cmd = ast_play_and_wait(chan, "vm-deleted");
06727 }
06728 else {
06729 if (play_folder == 0)
06730 vms.newmessages++;
06731 else if (play_folder == 1)
06732 vms.oldmessages++;
06733 cmd = ast_play_and_wait(chan, "vm-undeleted");
06734 }
06735 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
06736 if (vms.curmsg < vms.lastmsg) {
06737 vms.curmsg++;
06738 cmd = play_message(chan, vmu, &vms);
06739 } else {
06740 cmd = ast_play_and_wait(chan, "vm-nomore");
06741 }
06742 }
06743 } else
06744 cmd = 0;
06745 #ifdef IMAP_STORAGE
06746 deleted = 1;
06747 #endif
06748 break;
06749
06750 case '8':
06751 if (vms.lastmsg > -1) {
06752 cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain);
06753 if (cmd == ERROR_LOCK_PATH) {
06754 res = cmd;
06755 goto out;
06756 }
06757 } else
06758 cmd = ast_play_and_wait(chan, "vm-nomore");
06759 break;
06760 case '9':
06761 if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) {
06762
06763 cmd = 0;
06764 break;
06765 }
06766 if (useadsi)
06767 adsi_folders(chan, 1, "Save to folder...");
06768 cmd = get_folder2(chan, "vm-savefolder", 1);
06769 box = 0;
06770 if (cmd == '#') {
06771 cmd = 0;
06772 break;
06773 } else if (cmd > 0) {
06774 box = cmd = cmd - '0';
06775 cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd);
06776 if (cmd == ERROR_LOCK_PATH) {
06777 res = cmd;
06778 goto out;
06779 #ifdef IMAP_STORAGE
06780 } else if (cmd == 10) {
06781 goto out;
06782 #endif
06783 } else if (!cmd) {
06784 vms.deleted[vms.curmsg] = 1;
06785 } else {
06786 vms.deleted[vms.curmsg] = 0;
06787 vms.heard[vms.curmsg] = 0;
06788 }
06789 }
06790 make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg);
06791 if (useadsi)
06792 adsi_message(chan, &vms);
06793 snprintf(vms.fn, sizeof(vms.fn), "vm-%s", mbox(box));
06794 if (!cmd) {
06795 cmd = ast_play_and_wait(chan, "vm-message");
06796 if (!cmd)
06797 cmd = say_and_wait(chan, vms.curmsg + 1, chan->language);
06798 if (!cmd)
06799 cmd = ast_play_and_wait(chan, "vm-savedto");
06800 if (!cmd)
06801 cmd = vm_play_folder_name(chan, vms.fn);
06802 } else {
06803 cmd = ast_play_and_wait(chan, "vm-mailboxfull");
06804 }
06805 if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) {
06806 if (vms.curmsg < vms.lastmsg) {
06807 vms.curmsg++;
06808 cmd = play_message(chan, vmu, &vms);
06809 } else {
06810 cmd = ast_play_and_wait(chan, "vm-nomore");
06811 }
06812 }
06813 break;
06814 case '*':
06815 if (!vms.starting) {
06816 cmd = ast_play_and_wait(chan, "vm-onefor");
06817 if (!cmd)
06818 cmd = vm_play_folder_name(chan, vms.vmbox);
06819 if (!cmd)
06820 cmd = ast_play_and_wait(chan, "vm-opts");
06821 if (!cmd)
06822 cmd = vm_instructions(chan, &vms, 1);
06823 } else
06824 cmd = 0;
06825 break;
06826 case '0':
06827 cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain);
06828 if (useadsi)
06829 adsi_status(chan, &vms);
06830 break;
06831 default:
06832 cmd = vm_instructions(chan, &vms, 0);
06833 break;
06834 }
06835 }
06836 if ((cmd == 't') || (cmd == '#')) {
06837
06838 res = 0;
06839 } else {
06840
06841 res = -1;
06842 }
06843
06844 out:
06845 if (res > -1) {
06846 ast_stopstream(chan);
06847 adsi_goodbye(chan);
06848 if (valid) {
06849 if (silentexit)
06850 res = ast_play_and_wait(chan, "vm-dialout");
06851 else
06852 res = ast_play_and_wait(chan, "vm-goodbye");
06853 if (res > 0)
06854 res = 0;
06855 }
06856 if (useadsi)
06857 ast_adsi_unload_session(chan);
06858 }
06859 if (vmu)
06860 close_mailbox(&vms, vmu);
06861 if (valid) {
06862 snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context);
06863 manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL));
06864 run_externnotify(vmu->context, vmu->mailbox);
06865 }
06866 #ifdef IMAP_STORAGE
06867
06868 if(option_debug > 2)
06869 ast_log(LOG_DEBUG, "*** Checking if we can expunge, deleted set to %d, expungeonhangup set to %d\n",deleted,expungeonhangup);
06870 if (vmu && deleted == 1 && expungeonhangup == 1) {
06871 #ifdef HAVE_IMAP_TK2006
06872 if (LEVELUIDPLUS (vms.mailstream)) {
06873 mail_expunge_full(vms.mailstream,NIL,EX_UID);
06874 } else
06875 #endif
06876 mail_expunge(vms.mailstream);
06877 }
06878
06879
06880 vmstate_delete(&vms);
06881 #endif
06882 if (vmu)
06883 free_user(vmu);
06884 if (vms.deleted)
06885 free(vms.deleted);
06886 if (vms.heard)
06887 free(vms.heard);
06888 ast_module_user_remove(u);
06889
06890 return res;
06891 }
06892
06893 static int vm_exec(struct ast_channel *chan, void *data)
06894 {
06895 int res = 0;
06896 struct ast_module_user *u;
06897 char *tmp;
06898 struct leave_vm_options leave_options;
06899 struct ast_flags flags = { 0 };
06900 static int deprecate_warning = 0;
06901 char *opts[OPT_ARG_ARRAY_SIZE];
06902 AST_DECLARE_APP_ARGS(args,
06903 AST_APP_ARG(argv0);
06904 AST_APP_ARG(argv1);
06905 );
06906
06907 u = ast_module_user_add(chan);
06908
06909 memset(&leave_options, 0, sizeof(leave_options));
06910
06911 if (chan->_state != AST_STATE_UP)
06912 ast_answer(chan);
06913
06914 if (!ast_strlen_zero(data)) {
06915 tmp = ast_strdupa(data);
06916 AST_STANDARD_APP_ARGS(args, tmp);
06917 if (args.argc == 2) {
06918 if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) {
06919 ast_module_user_remove(u);
06920 return -1;
06921 }
06922 ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_PRIORITY_JUMP);
06923 if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
06924 int gain;
06925
06926 if (sscanf(opts[OPT_ARG_RECORDGAIN], "%d", &gain) != 1) {
06927 ast_log(LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]);
06928 ast_module_user_remove(u);
06929 return -1;
06930 } else {
06931 leave_options.record_gain = (signed char) gain;
06932 }
06933 }
06934 } else {
06935
06936 int old = 0;
06937 char *orig_argv0 = args.argv0;
06938 while (*(args.argv0)) {
06939 if (*(args.argv0) == 's') {
06940 old = 1;
06941 ast_set_flag(&leave_options, OPT_SILENT);
06942 } else if (*(args.argv0) == 'b') {
06943 old = 1;
06944 ast_set_flag(&leave_options, OPT_BUSY_GREETING);
06945 } else if (*(args.argv0) == 'u') {
06946 old = 1;
06947 ast_set_flag(&leave_options, OPT_UNAVAIL_GREETING);
06948 } else if (*(args.argv0) == 'j') {
06949 old = 1;
06950 ast_set_flag(&leave_options, OPT_PRIORITY_JUMP);
06951 } else
06952 break;
06953 (args.argv0)++;
06954 }
06955 if (!deprecate_warning && old) {
06956 deprecate_warning = 1;
06957 ast_log(LOG_WARNING, "Prefixing the mailbox with an option is deprecated ('%s').\n", orig_argv0);
06958 ast_log(LOG_WARNING, "Please move all leading options to the second argument.\n");
06959 }
06960 }
06961 } else {
06962 char tmp[256];
06963 res = ast_app_getdata(chan, "vm-whichbox", tmp, sizeof(tmp) - 1, 0);
06964 if (res < 0) {
06965 ast_module_user_remove(u);
06966 return res;
06967 }
06968 if (ast_strlen_zero(tmp)) {
06969 ast_module_user_remove(u);
06970 return 0;
06971 }
06972 args.argv0 = ast_strdupa(tmp);
06973 }
06974
06975 res = leave_voicemail(chan, args.argv0, &leave_options);
06976
06977 if (res == ERROR_LOCK_PATH) {
06978 ast_log(LOG_ERROR, "Could not leave voicemail. The path is already locked.\n");
06979
06980 if (ast_test_flag(&leave_options, OPT_PRIORITY_JUMP) || ast_opt_priority_jumping)
06981 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
06982 ast_log(LOG_WARNING, "Extension %s, priority %d doesn't exist.\n", chan->exten, chan->priority + 101);
06983 pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
06984 res = 0;
06985 }
06986
06987 ast_module_user_remove(u);
06988
06989 return res;
06990 }
06991
06992 static struct ast_vm_user *find_or_create(char *context, char *mbox)
06993 {
06994 struct ast_vm_user *vmu;
06995 AST_LIST_TRAVERSE(&users, vmu, list) {
06996 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mbox, vmu->mailbox))
06997 break;
06998 if (context && (!strcasecmp(context, vmu->context)) && (!strcasecmp(mbox, vmu->mailbox)))
06999 break;
07000 }
07001
07002 if (!vmu) {
07003 if ((vmu = ast_calloc(1, sizeof(*vmu)))) {
07004 ast_copy_string(vmu->context, context, sizeof(vmu->context));
07005 ast_copy_string(vmu->mailbox, mbox, sizeof(vmu->mailbox));
07006 AST_LIST_INSERT_TAIL(&users, vmu, list);
07007 }
07008 }
07009 return vmu;
07010 }
07011
07012 static int append_mailbox(char *context, char *mbox, char *data)
07013 {
07014
07015 char *tmp;
07016 char *stringp;
07017 char *s;
07018 struct ast_vm_user *vmu;
07019
07020 tmp = ast_strdupa(data);
07021
07022 if ((vmu = find_or_create(context, mbox))) {
07023 populate_defaults(vmu);
07024
07025 stringp = tmp;
07026 if ((s = strsep(&stringp, ",")))
07027 ast_copy_string(vmu->password, s, sizeof(vmu->password));
07028 if (stringp && (s = strsep(&stringp, ",")))
07029 ast_copy_string(vmu->fullname, s, sizeof(vmu->fullname));
07030 if (stringp && (s = strsep(&stringp, ",")))
07031 ast_copy_string(vmu->email, s, sizeof(vmu->email));
07032 if (stringp && (s = strsep(&stringp, ",")))
07033 ast_copy_string(vmu->pager, s, sizeof(vmu->pager));
07034 if (stringp && (s = strsep(&stringp, ",")))
07035 apply_options(vmu, s);
07036 }
07037 return 0;
07038 }
07039
07040 static int vm_box_exists(struct ast_channel *chan, void *data)
07041 {
07042 struct ast_module_user *u;
07043 struct ast_vm_user svm;
07044 char *context, *box;
07045 int priority_jump = 0;
07046 AST_DECLARE_APP_ARGS(args,
07047 AST_APP_ARG(mbox);
07048 AST_APP_ARG(options);
07049 );
07050
07051 if (ast_strlen_zero(data)) {
07052 ast_log(LOG_ERROR, "MailboxExists requires an argument: (vmbox[@context][|options])\n");
07053 return -1;
07054 }
07055
07056 u = ast_module_user_add(chan);
07057
07058 box = ast_strdupa(data);
07059
07060 AST_STANDARD_APP_ARGS(args, box);
07061
07062 if (args.options) {
07063 if (strchr(args.options, 'j'))
07064 priority_jump = 1;
07065 }
07066
07067 if ((context = strchr(args.mbox, '@'))) {
07068 *context = '\0';
07069 context++;
07070 }
07071
07072 if (find_user(&svm, context, args.mbox)) {
07073 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "SUCCESS");
07074 if (priority_jump || ast_opt_priority_jumping)
07075 if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
07076 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);
07077 } else
07078 pbx_builtin_setvar_helper(chan, "VMBOXEXISTSSTATUS", "FAILED");
07079 ast_module_user_remove(u);
07080 return 0;
07081 }
07082
07083 static int vmauthenticate(struct ast_channel *chan, void *data)
07084 {
07085 struct ast_module_user *u;
07086 char *s = data, *user=NULL, *context=NULL, mailbox[AST_MAX_EXTENSION] = "";
07087 struct ast_vm_user vmus;
07088 char *options = NULL;
07089 int silent = 0, skipuser = 0;
07090 int res = -1;
07091
07092 u = ast_module_user_add(chan);
07093
07094 if (s) {
07095 s = ast_strdupa(s);
07096 user = strsep(&s, "|");
07097 options = strsep(&s, "|");
07098 if (user) {
07099 s = user;
07100 user = strsep(&s, "@");
07101 context = strsep(&s, "");
07102 if (!ast_strlen_zero(user))
07103 skipuser++;
07104 ast_copy_string(mailbox, user, sizeof(mailbox));
07105 }
07106 }
07107
07108 if (options) {
07109 silent = (strchr(options, 's')) != NULL;
07110 }
07111
07112 if (!vm_authenticate(chan, mailbox, sizeof(mailbox), &vmus, context, NULL, skipuser, 3, silent)) {
07113 pbx_builtin_setvar_helper(chan, "AUTH_MAILBOX", mailbox);
07114 pbx_builtin_setvar_helper(chan, "AUTH_CONTEXT", vmus.context);
07115 ast_play_and_wait(chan, "auth-thankyou");
07116 res = 0;
07117 }
07118
07119 ast_module_user_remove(u);
07120 return res;
07121 }
07122
07123 static char voicemail_show_users_help[] =
07124 "Usage: voicemail show users [for <context>]\n"
07125 " Lists all mailboxes currently set up\n";
07126
07127 static char voicemail_show_zones_help[] =
07128 "Usage: voicemail show zones\n"
07129 " Lists zone message formats\n";
07130
07131 static int handle_voicemail_show_users(int fd, int argc, char *argv[])
07132 {
07133 struct ast_vm_user *vmu;
07134 char *output_format = "%-10s %-5s %-25s %-10s %6s\n";
07135
07136 if ((argc < 3) || (argc > 5) || (argc == 4)) return RESULT_SHOWUSAGE;
07137 else if ((argc == 5) && strcmp(argv[3],"for")) return RESULT_SHOWUSAGE;
07138
07139 AST_LIST_LOCK(&users);
07140 if (!AST_LIST_EMPTY(&users)) {
07141 if (argc == 3)
07142 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
07143 else {
07144 int count = 0;
07145 AST_LIST_TRAVERSE(&users, vmu, list) {
07146 if (!strcmp(argv[4],vmu->context))
07147 count++;
07148 }
07149 if (count) {
07150 ast_cli(fd, output_format, "Context", "Mbox", "User", "Zone", "NewMsg");
07151 } else {
07152 ast_cli(fd, "No such voicemail context \"%s\"\n", argv[4]);
07153 AST_LIST_UNLOCK(&users);
07154 return RESULT_FAILURE;
07155 }
07156 }
07157 AST_LIST_TRAVERSE(&users, vmu, list) {
07158 int newmsgs = 0, oldmsgs = 0;
07159 char count[12], tmp[256] = "";
07160
07161 if ((argc == 3) || ((argc == 5) && !strcmp(argv[4],vmu->context))) {
07162 snprintf(tmp, sizeof(tmp), "%s@%s", vmu->mailbox, ast_strlen_zero(vmu->context) ? "default" : vmu->context);
07163 inboxcount(tmp, &newmsgs, &oldmsgs);
07164 snprintf(count,sizeof(count),"%d",newmsgs);
07165 ast_cli(fd, output_format, vmu->context, vmu->mailbox, vmu->fullname, vmu->zonetag, count);
07166 }
07167 }
07168 } else {
07169 ast_cli(fd, "There are no voicemail users currently defined\n");
07170 AST_LIST_UNLOCK(&users);
07171 return RESULT_FAILURE;
07172 }
07173 AST_LIST_UNLOCK(&users);
07174 return RESULT_SUCCESS;
07175 }
07176
07177 static int handle_voicemail_show_zones(int fd, int argc, char *argv[])
07178 {
07179 struct vm_zone *zone;
07180 char *output_format = "%-15s %-20s %-45s\n";
07181 int res = RESULT_SUCCESS;
07182
07183 if (argc != 3)
07184 return RESULT_SHOWUSAGE;
07185
07186 AST_LIST_LOCK(&zones);
07187 if (!AST_LIST_EMPTY(&zones)) {
07188 ast_cli(fd, output_format, "Zone", "Timezone", "Message Format");
07189 AST_LIST_TRAVERSE(&zones, zone, list) {
07190 ast_cli(fd, output_format, zone->name, zone->timezone, zone->msg_format);
07191 }
07192 } else {
07193 ast_cli(fd, "There are no voicemail zones currently defined\n");
07194 res = RESULT_FAILURE;
07195 }
07196 AST_LIST_UNLOCK(&zones);
07197
07198 return res;
07199 }
07200
07201 static char *complete_voicemail_show_users(const char *line, const char *word, int pos, int state)
07202 {
07203 int which = 0;
07204 int wordlen;
07205 struct ast_vm_user *vmu;
07206 const char *context = "";
07207
07208
07209 if (pos > 4)
07210 return NULL;
07211 if (pos == 3)
07212 return (state == 0) ? ast_strdup("for") : NULL;
07213 wordlen = strlen(word);
07214 AST_LIST_TRAVERSE(&users, vmu, list) {
07215 if (!strncasecmp(word, vmu->context, wordlen)) {
07216 if (context && strcmp(context, vmu->context) && ++which > state)
07217 return ast_strdup(vmu->context);
07218
07219 context = vmu->context;
07220 }
07221 }
07222 return NULL;
07223 }
07224
07225 static struct ast_cli_entry cli_show_voicemail_users_deprecated = {
07226 { "show", "voicemail", "users", NULL },
07227 handle_voicemail_show_users, NULL,
07228 NULL, complete_voicemail_show_users };
07229
07230 static struct ast_cli_entry cli_show_voicemail_zones_deprecated = {
07231 { "show", "voicemail", "zones", NULL },
07232 handle_voicemail_show_zones, NULL,
07233 NULL, NULL };
07234
07235 static struct ast_cli_entry cli_voicemail[] = {
07236 { { "voicemail", "show", "users", NULL },
07237 handle_voicemail_show_users, "List defined voicemail boxes",
07238 voicemail_show_users_help, complete_voicemail_show_users, &cli_show_voicemail_users_deprecated },
07239
07240 { { "voicemail", "show", "zones", NULL },
07241 handle_voicemail_show_zones, "List zone message formats",
07242 voicemail_show_zones_help, NULL, &cli_show_voicemail_zones_deprecated },
07243 };
07244
07245 static int load_config(void)
07246 {
07247 struct ast_vm_user *cur;
07248 struct vm_zone *zcur;
07249 struct ast_config *cfg, *ucfg;
07250 char *cat;
07251 struct ast_variable *var;
07252 const char *notifystr = NULL;
07253 const char *smdistr = NULL;
07254 const char *astattach;
07255 const char *astsearch;
07256 const char *astsaycid;
07257 const char *send_voicemail;
07258 #ifdef IMAP_STORAGE
07259 const char *imap_server;
07260 const char *imap_port;
07261 const char *imap_flags;
07262 const char *imap_folder;
07263 const char *auth_user;
07264 const char *auth_password;
07265 const char *expunge_on_hangup;
07266 #endif
07267 const char *astcallop;
07268 const char *astreview;
07269 const char *asttempgreetwarn;
07270 const char *astskipcmd;
07271 const char *asthearenv;
07272 const char *astsaydurationinfo;
07273 const char *astsaydurationminfo;
07274 const char *silencestr;
07275 const char *maxmsgstr;
07276 const char *astdirfwd;
07277 const char *thresholdstr;
07278 const char *fmt;
07279 const char *astemail;
07280 const char *ucontext;
07281 const char *astmailcmd = SENDMAIL;
07282 const char *astforcename;
07283 const char *astforcegreet;
07284 const char *s;
07285 char *q,*stringp;
07286 const char *dialoutcxt = NULL;
07287 const char *callbackcxt = NULL;
07288 const char *exitcxt = NULL;
07289 const char *extpc;
07290 const char *emaildateformatstr;
07291 const char *volgainstr;
07292 int x;
07293 int tmpadsi[4];
07294
07295 cfg = ast_config_load(VOICEMAIL_CONFIG);
07296
07297 AST_LIST_LOCK(&users);
07298 while ((cur = AST_LIST_REMOVE_HEAD(&users, list))) {
07299 ast_set_flag(cur, VM_ALLOCED);
07300 free_user(cur);
07301 }
07302
07303 AST_LIST_LOCK(&zones);
07304 while ((zcur = AST_LIST_REMOVE_HEAD(&zones, list)))
07305 free_zone(zcur);
07306 AST_LIST_UNLOCK(&zones);
07307
07308 memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));
07309
07310 if (cfg) {
07311
07312
07313 if (!(ucontext = ast_variable_retrieve(cfg, "general", "userscontext")))
07314 ucontext = "default";
07315 ast_copy_string(userscontext, ucontext, sizeof(userscontext));
07316
07317 if (!(astattach = ast_variable_retrieve(cfg, "general", "attach")))
07318 astattach = "yes";
07319 ast_set2_flag((&globalflags), ast_true(astattach), VM_ATTACH);
07320
07321 if (!(astsearch = ast_variable_retrieve(cfg, "general", "searchcontexts")))
07322 astsearch = "no";
07323 ast_set2_flag((&globalflags), ast_true(astsearch), VM_SEARCH);
07324
07325 volgain = 0.0;
07326 if ((volgainstr = ast_variable_retrieve(cfg, "general", "volgain")))
07327 sscanf(volgainstr, "%lf", &volgain);
07328
07329 #ifdef ODBC_STORAGE
07330 strcpy(odbc_database, "asterisk");
07331 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
07332 ast_copy_string(odbc_database, thresholdstr, sizeof(odbc_database));
07333 }
07334 strcpy(odbc_table, "voicemessages");
07335 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "odbctable"))) {
07336 ast_copy_string(odbc_table, thresholdstr, sizeof(odbc_table));
07337 }
07338 #endif
07339
07340 strcpy(mailcmd, SENDMAIL);
07341 if ((astmailcmd = ast_variable_retrieve(cfg, "general", "mailcmd")))
07342 ast_copy_string(mailcmd, astmailcmd, sizeof(mailcmd));
07343
07344 maxsilence = 0;
07345 if ((silencestr = ast_variable_retrieve(cfg, "general", "maxsilence"))) {
07346 maxsilence = atoi(silencestr);
07347 if (maxsilence > 0)
07348 maxsilence *= 1000;
07349 }
07350
07351 if (!(maxmsgstr = ast_variable_retrieve(cfg, "general", "maxmsg"))) {
07352 maxmsg = MAXMSG;
07353 } else {
07354 maxmsg = atoi(maxmsgstr);
07355 if (maxmsg <= 0) {
07356 ast_log(LOG_WARNING, "Invalid number of messages per folder '%s'. Using default value %i\n", maxmsgstr, MAXMSG);
07357 maxmsg = MAXMSG;
07358 } else if (maxmsg > MAXMSGLIMIT) {
07359 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value '%s'\n", MAXMSGLIMIT, maxmsgstr);
07360 maxmsg = MAXMSGLIMIT;
07361 }
07362 }
07363
07364
07365 if ((emaildateformatstr = ast_variable_retrieve(cfg, "general", "emaildateformat"))) {
07366 ast_copy_string(emaildateformat, emaildateformatstr, sizeof(emaildateformat));
07367 }
07368
07369
07370 if ((extpc = ast_variable_retrieve(cfg, "general", "externpass"))) {
07371 ast_copy_string(ext_pass_cmd,extpc,sizeof(ext_pass_cmd));
07372 }
07373 #ifdef IMAP_STORAGE
07374
07375 if ((imap_server = ast_variable_retrieve(cfg, "general", "imapserver"))) {
07376 ast_copy_string(imapserver, imap_server, sizeof(imapserver));
07377 } else {
07378 ast_copy_string(imapserver,"localhost", sizeof(imapserver));
07379 }
07380
07381 if ((imap_port = ast_variable_retrieve(cfg, "general", "imapport"))) {
07382 ast_copy_string(imapport, imap_port, sizeof(imapport));
07383 } else {
07384 ast_copy_string(imapport,"143", sizeof(imapport));
07385 }
07386
07387 if ((imap_flags = ast_variable_retrieve(cfg, "general", "imapflags"))) {
07388 ast_copy_string(imapflags, imap_flags, sizeof(imapflags));
07389 }
07390
07391 if ((auth_user = ast_variable_retrieve(cfg, "general", "authuser"))) {
07392 ast_copy_string(authuser, auth_user, sizeof(authuser));
07393 }
07394
07395 if ((auth_password = ast_variable_retrieve(cfg, "general", "authpassword"))) {
07396 ast_copy_string(authpassword, auth_password, sizeof(authpassword));
07397 }
07398
07399 if ((expunge_on_hangup = ast_variable_retrieve(cfg, "general", "expungeonhangup"))) {
07400 if(ast_false(expunge_on_hangup))
07401 expungeonhangup = 0;
07402 else
07403 expungeonhangup = 1;
07404 } else {
07405 expungeonhangup = 1;
07406 }
07407
07408 if ((imap_folder = ast_variable_retrieve(cfg, "general", "imapfolder"))) {
07409 ast_copy_string(imapfolder, imap_folder, sizeof(imapfolder));
07410 } else {
07411 ast_copy_string(imapfolder,"INBOX", sizeof(imapfolder));
07412 }
07413 #endif
07414
07415
07416 if ((notifystr = ast_variable_retrieve(cfg, "general", "externnotify"))) {
07417 ast_copy_string(externnotify, notifystr, sizeof(externnotify));
07418 if (option_debug > 2)
07419 ast_log(LOG_DEBUG, "found externnotify: %s\n", externnotify);
07420 if (!strcasecmp(externnotify, "smdi")) {
07421 if (option_debug)
07422 ast_log(LOG_DEBUG, "Using SMDI for external voicemail notification\n");
07423 if ((smdistr = ast_variable_retrieve(cfg, "general", "smdiport"))) {
07424 smdi_iface = ast_smdi_interface_find(smdistr);
07425 } else {
07426 if (option_debug)
07427 ast_log(LOG_DEBUG, "No SMDI interface set, trying default (/dev/ttyS0)\n");
07428 smdi_iface = ast_smdi_interface_find("/dev/ttyS0");
07429 }
07430
07431 if (!smdi_iface) {
07432 ast_log(LOG_ERROR, "No valid SMDI interface specfied, disabling external voicemail notification\n");
07433 externnotify[0] = '\0';
07434 } else {
07435 if (option_debug > 2)
07436 ast_log(LOG_DEBUG, "Using SMDI port %s\n", smdi_iface->name);
07437 }
07438 }
07439 } else {
07440 externnotify[0] = '\0';
07441 }
07442
07443
07444 silencethreshold = 256;
07445 if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
07446 silencethreshold = atoi(thresholdstr);
07447
07448 if (!(astemail = ast_variable_retrieve(cfg, "general", "serveremail")))
07449 astemail = ASTERISK_USERNAME;
07450 ast_copy_string(serveremail, astemail, sizeof(serveremail));
07451
07452 vmmaxmessage = 0;
07453 if ((s = ast_variable_retrieve(cfg, "general", "maxmessage"))) {
07454 if (sscanf(s, "%d", &x) == 1) {
07455 vmmaxmessage = x;
07456 } else {
07457 ast_log(LOG_WARNING, "Invalid max message time length\n");
07458 }
07459 }
07460
07461 vmminmessage = 0;
07462 if ((s = ast_variable_retrieve(cfg, "general", "minmessage"))) {
07463 if (sscanf(s, "%d", &x) == 1) {
07464 vmminmessage = x;
07465 if (maxsilence <= vmminmessage)
07466 ast_log(LOG_WARNING, "maxsilence should be less than minmessage or you may get empty messages\n");
07467 } else {
07468 ast_log(LOG_WARNING, "Invalid min message time length\n");
07469 }
07470 }
07471 fmt = ast_variable_retrieve(cfg, "general", "format");
07472 if (!fmt)
07473 fmt = "wav";
07474 ast_copy_string(vmfmts, fmt, sizeof(vmfmts));
07475
07476 skipms = 3000;
07477 if ((s = ast_variable_retrieve(cfg, "general", "maxgreet"))) {
07478 if (sscanf(s, "%d", &x) == 1) {
07479 maxgreet = x;
07480 } else {
07481 ast_log(LOG_WARNING, "Invalid max message greeting length\n");
07482 }
07483 }
07484
07485 if ((s = ast_variable_retrieve(cfg, "general", "skipms"))) {
07486 if (sscanf(s, "%d", &x) == 1) {
07487 skipms = x;
07488 } else {
07489 ast_log(LOG_WARNING, "Invalid skipms value\n");
07490 }
07491 }
07492
07493 maxlogins = 3;
07494 if ((s = ast_variable_retrieve(cfg, "general", "maxlogins"))) {
07495 if (sscanf(s, "%d", &x) == 1) {
07496 maxlogins = x;
07497 } else {
07498 ast_log(LOG_WARNING, "Invalid max failed login attempts\n");
07499 }
07500 }
07501
07502
07503 if (!(astforcename = ast_variable_retrieve(cfg, "general", "forcename")))
07504 astforcename = "no";
07505 ast_set2_flag((&globalflags), ast_true(astforcename), VM_FORCENAME);
07506
07507
07508 if (!(astforcegreet = ast_variable_retrieve(cfg, "general", "forcegreetings")))
07509 astforcegreet = "no";
07510 ast_set2_flag((&globalflags), ast_true(astforcegreet), VM_FORCEGREET);
07511
07512 if ((s = ast_variable_retrieve(cfg, "general", "cidinternalcontexts"))){
07513 if (option_debug > 2)
07514 ast_log(LOG_DEBUG,"VM_CID Internal context string: %s\n",s);
07515 stringp = ast_strdupa(s);
07516 for (x = 0 ; x < MAX_NUM_CID_CONTEXTS ; x++){
07517 if (!ast_strlen_zero(stringp)) {
07518 q = strsep(&stringp,",");
07519 while ((*q == ' ')||(*q == '\t'))
07520 q++;
07521 ast_copy_string(cidinternalcontexts[x], q, sizeof(cidinternalcontexts[x]));
07522 if (option_debug > 2)
07523 ast_log(LOG_DEBUG,"VM_CID Internal context %d: %s\n", x, cidinternalcontexts[x]);
07524 } else {
07525 cidinternalcontexts[x][0] = '\0';
07526 }
07527 }
07528 }
07529 if (!(astreview = ast_variable_retrieve(cfg, "general", "review"))){
07530 if (option_debug)
07531 ast_log(LOG_DEBUG,"VM Review Option disabled globally\n");
07532 astreview = "no";
07533 }
07534 ast_set2_flag((&globalflags), ast_true(astreview), VM_REVIEW);
07535
07536
07537 if (!(asttempgreetwarn = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) {
07538 if (option_debug)
07539 ast_log(LOG_DEBUG, "VM Temperary Greeting Reminder Option disabled globally\n");
07540 asttempgreetwarn = "no";
07541 } else {
07542 if (option_debug)
07543 ast_log(LOG_DEBUG, "VM Temperary Greeting Reminder Option enabled globally\n");
07544 }
07545 ast_set2_flag((&globalflags), ast_true(asttempgreetwarn), VM_TEMPGREETWARN);
07546
07547 if (!(astcallop = ast_variable_retrieve(cfg, "general", "operator"))){
07548 if (option_debug)
07549 ast_log(LOG_DEBUG,"VM Operator break disabled globally\n");
07550 astcallop = "no";
07551 }
07552 ast_set2_flag((&globalflags), ast_true(astcallop), VM_OPERATOR);
07553
07554 if (!(astsaycid = ast_variable_retrieve(cfg, "general", "saycid"))) {
07555 if (option_debug)
07556 ast_log(LOG_DEBUG,"VM CID Info before msg disabled globally\n");
07557 astsaycid = "no";
07558 }
07559 ast_set2_flag((&globalflags), ast_true(astsaycid), VM_SAYCID);
07560
07561 if (!(send_voicemail = ast_variable_retrieve(cfg,"general", "sendvoicemail"))){
07562 if (option_debug)
07563 ast_log(LOG_DEBUG,"Send Voicemail msg disabled globally\n");
07564 send_voicemail = "no";
07565 }
07566 ast_set2_flag((&globalflags), ast_true(send_voicemail), VM_SVMAIL);
07567
07568 if (!(asthearenv = ast_variable_retrieve(cfg, "general", "envelope"))) {
07569 if (option_debug)
07570 ast_log(LOG_DEBUG,"ENVELOPE before msg enabled globally\n");
07571 asthearenv = "yes";
07572 }
07573 ast_set2_flag((&globalflags), ast_true(asthearenv), VM_ENVELOPE);
07574
07575 if (!(astsaydurationinfo = ast_variable_retrieve(cfg, "general", "sayduration"))) {
07576 if (option_debug)
07577 ast_log(LOG_DEBUG,"Duration info before msg enabled globally\n");
07578 astsaydurationinfo = "yes";
07579 }
07580 ast_set2_flag((&globalflags), ast_true(astsaydurationinfo), VM_SAYDURATION);
07581
07582 saydurationminfo = 2;
07583 if ((astsaydurationminfo = ast_variable_retrieve(cfg, "general", "saydurationm"))) {
07584 if (sscanf(astsaydurationminfo, "%d", &x) == 1) {
07585 saydurationminfo = x;
07586 } else {
07587 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
07588 }
07589 }
07590
07591 if (!(astskipcmd = ast_variable_retrieve(cfg, "general", "nextaftercmd"))) {
07592 if (option_debug)
07593 ast_log(LOG_DEBUG,"We are not going to skip to the next msg after save/delete\n");
07594 astskipcmd = "no";
07595 }
07596 ast_set2_flag((&globalflags), ast_true(astskipcmd), VM_SKIPAFTERCMD);
07597
07598 if ((dialoutcxt = ast_variable_retrieve(cfg, "general", "dialout"))) {
07599 ast_copy_string(dialcontext, dialoutcxt, sizeof(dialcontext));
07600 if (option_debug)
07601 ast_log(LOG_DEBUG, "found dialout context: %s\n", dialcontext);
07602 } else {
07603 dialcontext[0] = '\0';
07604 }
07605
07606 if ((callbackcxt = ast_variable_retrieve(cfg, "general", "callback"))) {
07607 ast_copy_string(callcontext, callbackcxt, sizeof(callcontext));
07608 if (option_debug)
07609 ast_log(LOG_DEBUG, "found callback context: %s\n", callcontext);
07610 } else {
07611 callcontext[0] = '\0';
07612 }
07613
07614 if ((exitcxt = ast_variable_retrieve(cfg, "general", "exitcontext"))) {
07615 ast_copy_string(exitcontext, exitcxt, sizeof(exitcontext));
07616 if (option_debug)
07617 ast_log(LOG_DEBUG, "found operator context: %s\n", exitcontext);
07618 } else {
07619 exitcontext[0] = '\0';
07620 }
07621
07622 if (!(astdirfwd = ast_variable_retrieve(cfg, "general", "usedirectory")))
07623 astdirfwd = "no";
07624 ast_set2_flag((&globalflags), ast_true(astdirfwd), VM_DIRECFORWARD);
07625 if ((ucfg = ast_config_load("users.conf"))) {
07626 for (cat = ast_category_browse(ucfg, NULL); cat ; cat = ast_category_browse(ucfg, cat)) {
07627 if (!ast_true(ast_config_option(ucfg, cat, "hasvoicemail")))
07628 continue;
07629 if ((cur = find_or_create(userscontext, cat))) {
07630 populate_defaults(cur);
07631 apply_options_full(cur, ast_variable_browse(ucfg, cat));
07632 ast_copy_string(cur->context, userscontext, sizeof(cur->context));
07633 }
07634 }
07635 ast_config_destroy(ucfg);
07636 }
07637 cat = ast_category_browse(cfg, NULL);
07638 while (cat) {
07639 if (strcasecmp(cat, "general")) {
07640 var = ast_variable_browse(cfg, cat);
07641 if (strcasecmp(cat, "zonemessages")) {
07642
07643 while (var) {
07644 append_mailbox(cat, var->name, var->value);
07645 var = var->next;
07646 }
07647 } else {
07648
07649 while (var) {
07650 struct vm_zone *z;
07651 if ((z = ast_malloc(sizeof(*z)))) {
07652 char *msg_format, *timezone;
07653 msg_format = ast_strdupa(var->value);
07654 timezone = strsep(&msg_format, "|");
07655 if (msg_format) {
07656 ast_copy_string(z->name, var->name, sizeof(z->name));
07657 ast_copy_string(z->timezone, timezone, sizeof(z->timezone));
07658 ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
07659 AST_LIST_LOCK(&zones);
07660 AST_LIST_INSERT_HEAD(&zones, z, list);
07661 AST_LIST_UNLOCK(&zones);
07662 } else {
07663 ast_log(LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
07664 free(z);
07665 }
07666 } else {
07667 free(z);
07668 AST_LIST_UNLOCK(&users);
07669 ast_config_destroy(cfg);
07670 return -1;
07671 }
07672 var = var->next;
07673 }
07674 }
07675 }
07676 cat = ast_category_browse(cfg, cat);
07677 }
07678 memset(fromstring,0,sizeof(fromstring));
07679 memset(pagerfromstring,0,sizeof(pagerfromstring));
07680 memset(emailtitle,0,sizeof(emailtitle));
07681 strcpy(charset, "ISO-8859-1");
07682 if (emailbody) {
07683 free(emailbody);
07684 emailbody = NULL;
07685 }
07686 if (emailsubject) {
07687 free(emailsubject);
07688 emailsubject = NULL;
07689 }
07690 if (pagerbody) {
07691 free(pagerbody);
07692 pagerbody = NULL;
07693 }
07694 if (pagersubject) {
07695 free(pagersubject);
07696 pagersubject = NULL;
07697 }
07698 if ((s = ast_variable_retrieve(cfg, "general", "pbxskip")))
07699 ast_set2_flag((&globalflags), ast_true(s), VM_PBXSKIP);
07700 if ((s = ast_variable_retrieve(cfg, "general", "fromstring")))
07701 ast_copy_string(fromstring,s,sizeof(fromstring));
07702 if ((s = ast_variable_retrieve(cfg, "general", "pagerfromstring")))
07703 ast_copy_string(pagerfromstring,s,sizeof(pagerfromstring));
07704 if ((s = ast_variable_retrieve(cfg, "general", "charset")))
07705 ast_copy_string(charset,s,sizeof(charset));
07706 if ((s = ast_variable_retrieve(cfg, "general", "adsifdn"))) {
07707 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
07708 for (x = 0; x < 4; x++) {
07709 memcpy(&adsifdn[x], &tmpadsi[x], 1);
07710 }
07711 }
07712 if ((s = ast_variable_retrieve(cfg, "general", "adsisec"))) {
07713 sscanf(s, "%2x%2x%2x%2x", &tmpadsi[0], &tmpadsi[1], &tmpadsi[2], &tmpadsi[3]);
07714 for (x = 0; x < 4; x++) {
07715 memcpy(&adsisec[x], &tmpadsi[x], 1);
07716 }
07717 }
07718 if ((s = ast_variable_retrieve(cfg, "general", "adsiver")))
07719 if (atoi(s)) {
07720 adsiver = atoi(s);
07721 }
07722 if ((s = ast_variable_retrieve(cfg, "general", "emailtitle"))) {
07723 ast_log(LOG_NOTICE, "Keyword 'emailtitle' is DEPRECATED, please use 'emailsubject' instead.\n");
07724 ast_copy_string(emailtitle,s,sizeof(emailtitle));
07725 }
07726 if ((s = ast_variable_retrieve(cfg, "general", "emailsubject")))
07727 emailsubject = ast_strdup(s);
07728 if ((s = ast_variable_retrieve(cfg, "general", "emailbody"))) {
07729 char *tmpread, *tmpwrite;
07730 emailbody = ast_strdup(s);
07731
07732
07733 tmpread = tmpwrite = emailbody;
07734 while ((tmpwrite = strchr(tmpread,'\\'))) {
07735 switch (tmpwrite[1]) {
07736 case 'r':
07737 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07738 *tmpwrite = '\r';
07739 break;
07740 case 'n':
07741 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07742 *tmpwrite = '\n';
07743 break;
07744 case 't':
07745 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07746 *tmpwrite = '\t';
07747 break;
07748 default:
07749 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
07750 }
07751 tmpread = tmpwrite + 1;
07752 }
07753 }
07754 if ((s = ast_variable_retrieve(cfg, "general", "pagersubject")))
07755 pagersubject = ast_strdup(s);
07756 if ((s = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
07757 char *tmpread, *tmpwrite;
07758 pagerbody = ast_strdup(s);
07759
07760
07761 tmpread = tmpwrite = pagerbody;
07762 while ((tmpwrite = strchr(tmpread, '\\'))) {
07763 switch (tmpwrite[1]) {
07764 case 'r':
07765 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07766 *tmpwrite = '\r';
07767 break;
07768 case 'n':
07769 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07770 *tmpwrite = '\n';
07771 break;
07772 case 't':
07773 memmove(tmpwrite + 1, tmpwrite + 2, strlen(tmpwrite + 2) + 1);
07774 *tmpwrite = '\t';
07775 break;
07776 default:
07777 ast_log(LOG_NOTICE, "Substitution routine does not support this character: %c\n", tmpwrite[1]);
07778 }
07779 tmpread = tmpwrite + 1;
07780 }
07781 }
07782 AST_LIST_UNLOCK(&users);
07783 ast_config_destroy(cfg);
07784 return 0;
07785 } else {
07786 AST_LIST_UNLOCK(&users);
07787 ast_log(LOG_WARNING, "Failed to load configuration file.\n");
07788 return 0;
07789 }
07790 }
07791
07792 static int reload(void)
07793 {
07794 return(load_config());
07795 }
07796
07797 static int unload_module(void)
07798 {
07799 int res;
07800
07801 res = ast_unregister_application(app);
07802 res |= ast_unregister_application(app2);
07803 res |= ast_unregister_application(app3);
07804 res |= ast_unregister_application(app4);
07805 ast_cli_unregister_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
07806 ast_uninstall_vm_functions();
07807
07808 ast_module_user_hangup_all();
07809
07810 return res;
07811 }
07812
07813 static int load_module(void)
07814 {
07815 int res;
07816 my_umask = umask(0);
07817 umask(my_umask);
07818 res = ast_register_application(app, vm_exec, synopsis_vm, descrip_vm);
07819 res |= ast_register_application(app2, vm_execmain, synopsis_vmain, descrip_vmain);
07820 res |= ast_register_application(app3, vm_box_exists, synopsis_vm_box_exists, descrip_vm_box_exists);
07821 res |= ast_register_application(app4, vmauthenticate, synopsis_vmauthenticate, descrip_vmauthenticate);
07822 if (res)
07823 return(res);
07824
07825 if ((res=load_config())) {
07826 return(res);
07827 }
07828
07829 ast_cli_register_multiple(cli_voicemail, sizeof(cli_voicemail) / sizeof(struct ast_cli_entry));
07830
07831
07832 snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
07833
07834 ast_install_vm_functions(has_voicemail, inboxcount, messagecount);
07835
07836 return res;
07837 }
07838
07839 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context)
07840 {
07841 int cmd = 0;
07842 char destination[80] = "";
07843 int retries = 0;
07844
07845 if (!num) {
07846 if (option_verbose > 2)
07847 ast_verbose( VERBOSE_PREFIX_3 "Destination number will be entered manually\n");
07848 while (retries < 3 && cmd != 't') {
07849 destination[1] = '\0';
07850 destination[0] = cmd = ast_play_and_wait(chan,"vm-enter-num-to-call");
07851 if (!cmd)
07852 destination[0] = cmd = ast_play_and_wait(chan, "vm-then-pound");
07853 if (!cmd)
07854 destination[0] = cmd = ast_play_and_wait(chan, "vm-star-cancel");
07855 if (!cmd) {
07856 cmd = ast_waitfordigit(chan, 6000);
07857 if (cmd)
07858 destination[0] = cmd;
07859 }
07860 if (!cmd) {
07861 retries++;
07862 } else {
07863
07864 if (cmd < 0)
07865 return 0;
07866 if (cmd == '*') {
07867 if (option_verbose > 2)
07868 ast_verbose( VERBOSE_PREFIX_3 "User hit '*' to cancel outgoing call\n");
07869 return 0;
07870 }
07871 if ((cmd = ast_readstring(chan,destination + strlen(destination),sizeof(destination)-1,6000,10000,"#")) < 0)
07872 retries++;
07873 else
07874 cmd = 't';
07875 }
07876 }
07877 if (retries >= 3) {
07878 return 0;
07879 }
07880
07881 } else {
07882 if (option_verbose > 2)
07883 ast_verbose( VERBOSE_PREFIX_3 "Destination number is CID number '%s'\n", num);
07884 ast_copy_string(destination, num, sizeof(destination));
07885 }
07886
07887 if (!ast_strlen_zero(destination)) {
07888 if (destination[strlen(destination) -1 ] == '*')
07889 return 0;
07890 if (option_verbose > 2)
07891 ast_verbose( VERBOSE_PREFIX_3 "Placing outgoing call to extension '%s' in context '%s' from context '%s'\n", destination, outgoing_context, chan->context);
07892 ast_copy_string(chan->exten, destination, sizeof(chan->exten));
07893 ast_copy_string(chan->context, outgoing_context, sizeof(chan->context));
07894 chan->priority = 0;
07895 return 9;
07896 }
07897 return 0;
07898 }
07899
07900 static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int msg, int option, signed char record_gain)
07901 {
07902 int res = 0;
07903 #ifdef IMAP_STORAGE
07904 char origtimeS[256],cidS[256],contextS[256];
07905 char *header_content,*temp;
07906 #endif
07907 char filename[PATH_MAX];
07908 struct ast_config *msg_cfg = NULL;
07909 const char *origtime, *context;
07910 char *cid, *name, *num;
07911 int retries = 0;
07912
07913 vms->starting = 0;
07914 #ifdef IMAP_STORAGE
07915
07916
07917 if(option_debug > 2)
07918 ast_log (LOG_DEBUG,"Before mail_fetchheaders, curmsg is: %d, imap messages is %lu\n",vms->curmsg, vms->msgArray[vms->curmsg]);
07919 if (vms->msgArray[vms->curmsg] == 0) {
07920 ast_log (LOG_WARNING,"Trying to access unknown message\n");
07921 return -1;
07922 }
07923
07924
07925 header_content = mail_fetchheader (vms->mailstream, vms->msgArray[vms->curmsg]);
07926
07927 if (ast_strlen_zero(header_content)) {
07928 ast_log (LOG_ERROR,"Could not fetch header for message number %ld\n",vms->msgArray[vms->curmsg]);
07929 return -1;
07930 }
07931
07932
07933 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Caller-ID-Num:");
07934
07935 if (temp)
07936 ast_copy_string(cidS,temp, sizeof(cidS));
07937 else
07938 cidS[0] = '\0';
07939
07940 cid = &cidS[0];
07941 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Context:");
07942
07943 if (temp)
07944 ast_copy_string(contextS,temp, sizeof(contextS));
07945 else
07946 contextS[0] = '\0';
07947
07948 context = &contextS[0];
07949 temp = get_header_by_tag(header_content, "X-Asterisk-VM-Orig-time:");
07950
07951 if (temp)
07952 ast_copy_string(origtimeS,temp, sizeof(origtimeS));
07953 else
07954 origtimeS[0] = '\0';
07955
07956 origtime = &origtimeS[0];
07957
07958 ast_copy_string(filename, "IMAP_STORAGE", sizeof(filename));
07959 #else
07960 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
07961
07962
07963
07964 make_file(vms->fn2, sizeof(vms->fn2), vms->curdir, vms->curmsg);
07965 snprintf(filename,sizeof(filename), "%s.txt", vms->fn2);
07966 RETRIEVE(vms->curdir, vms->curmsg);
07967 msg_cfg = ast_config_load(filename);
07968 DISPOSE(vms->curdir, vms->curmsg);
07969 if (!msg_cfg) {
07970 ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename);
07971 return 0;
07972 }
07973
07974 if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) {
07975 ast_config_destroy(msg_cfg);
07976 return 0;
07977 }
07978
07979 cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid"));
07980
07981 context = ast_variable_retrieve(msg_cfg, "message", "context");
07982 if (!strncasecmp("macro",context,5))
07983 context = ast_variable_retrieve(msg_cfg, "message","macrocontext");
07984 #endif
07985 switch (option) {
07986 case 3:
07987 if (!res)
07988 res = play_message_datetime(chan, vmu, origtime, filename);
07989 if (!res)
07990 res = play_message_callerid(chan, vms, cid, context, 0);
07991
07992 res = 't';
07993 break;
07994
07995 case 2:
07996
07997 if (ast_strlen_zero(cid))
07998 break;
07999
08000 ast_callerid_parse(cid, &name, &num);
08001 while ((res > -1) && (res != 't')) {
08002 switch (res) {
08003 case '1':
08004 if (num) {
08005
08006 res = dialout(chan, vmu, num, vmu->callback);
08007 if (res) {
08008 ast_config_destroy(msg_cfg);
08009 return 9;
08010 }
08011 } else {
08012 res = '2';
08013 }
08014 break;
08015
08016 case '2':
08017
08018 if (!ast_strlen_zero(vmu->dialout)) {
08019 res = dialout(chan, vmu, NULL, vmu->dialout);
08020 if (res) {
08021 ast_config_destroy(msg_cfg);
08022 return 9;
08023 }
08024 } else {
08025 if (option_verbose > 2)
08026 ast_verbose( VERBOSE_PREFIX_3 "Caller can not specify callback number - no dialout context available\n");
08027 res = ast_play_and_wait(chan, "vm-sorry");
08028 }
08029 ast_config_destroy(msg_cfg);
08030 return res;
08031 case '*':
08032 res = 't';
08033 break;
08034 case '3':
08035 case '4':
08036 case '5':
08037 case '6':
08038 case '7':
08039 case '8':
08040 case '9':
08041 case '0':
08042
08043 res = ast_play_and_wait(chan, "vm-sorry");
08044 retries++;
08045 break;
08046 default:
08047 if (num) {
08048 if (option_verbose > 2)
08049 ast_verbose( VERBOSE_PREFIX_3 "Confirm CID number '%s' is number to use for callback\n", num);
08050 res = ast_play_and_wait(chan, "vm-num-i-have");
08051 if (!res)
08052 res = play_message_callerid(chan, vms, num, vmu->context, 1);
08053 if (!res)
08054 res = ast_play_and_wait(chan, "vm-tocallnum");
08055
08056 if (!ast_strlen_zero(vmu->dialout)) {
08057 if (!res)
08058 res = ast_play_and_wait(chan, "vm-calldiffnum");
08059 }
08060 } else {
08061 res = ast_play_and_wait(chan, "vm-nonumber");
08062 if (!ast_strlen_zero(vmu->dialout)) {
08063 if (!res)
08064 res = ast_play_and_wait(chan, "vm-toenternumber");
08065 }
08066 }
08067 if (!res)
08068 res = ast_play_and_wait(chan, "vm-star-cancel");
08069 if (!res)
08070 res = ast_waitfordigit(chan, 6000);
08071 if (!res) {
08072 retries++;
08073 if (retries > 3)
08074 res = 't';
08075 }
08076 break;
08077
08078 }
08079 if (res == 't')
08080 res = 0;
08081 else if (res == '*')
08082 res = -1;
08083 }
08084 break;
08085
08086 case 1:
08087
08088 if (ast_strlen_zero(cid))
08089 break;
08090
08091 ast_callerid_parse(cid, &name, &num);
08092 if (!num) {
08093 if (option_verbose > 2)
08094 ast_verbose(VERBOSE_PREFIX_3 "No CID number available, no reply sent\n");
08095 if (!res)
08096 res = ast_play_and_wait(chan, "vm-nonumber");
08097 ast_config_destroy(msg_cfg);
08098 return res;
08099 } else {
08100 struct ast_vm_user vmu2;
08101 if (find_user(&vmu2, vmu->context, num)) {
08102 struct leave_vm_options leave_options;
08103 char mailbox[AST_MAX_EXTENSION * 2 + 2];
08104 snprintf(mailbox, sizeof(mailbox), "%s@%s", num, vmu->context);
08105
08106 if (option_verbose > 2)
08107 ast_verbose(VERBOSE_PREFIX_3 "Leaving voicemail for '%s' in context '%s'\n", num, vmu->context);
08108
08109 memset(&leave_options, 0, sizeof(leave_options));
08110 leave_options.record_gain = record_gain;
08111 res = leave_voicemail(chan, mailbox, &leave_options);
08112 if (!res)
08113 res = 't';
08114 ast_config_destroy(msg_cfg);
08115 return res;
08116 } else {
08117
08118 if (option_verbose > 2)
08119 ast_verbose( VERBOSE_PREFIX_3 "No mailbox number '%s' in context '%s', no reply sent\n", num, vmu->context);
08120 ast_play_and_wait(chan, "vm-nobox");
08121 res = 't';
08122 ast_config_destroy(msg_cfg);
08123 return res;
08124 }
08125 }
08126 res = 0;
08127
08128 break;
08129 }
08130
08131 #ifndef IMAP_STORAGE
08132 ast_config_destroy(msg_cfg);
08133
08134 if (!res) {
08135 make_file(vms->fn, sizeof(vms->fn), vms->curdir, msg);
08136 vms->heard[msg] = 1;
08137 res = wait_file(chan, vms, vms->fn);
08138 }
08139 #endif
08140 return res;
08141 }
08142
08143 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt,
08144 int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
08145 signed char record_gain, struct vm_state *vms)
08146 {
08147
08148 int res = 0;
08149 int cmd = 0;
08150 int max_attempts = 3;
08151 int attempts = 0;
08152 int recorded = 0;
08153 int message_exists = 0;
08154 signed char zero_gain = 0;
08155 char tempfile[PATH_MAX];
08156 char *acceptdtmf = "#";
08157 char *canceldtmf = "";
08158
08159
08160
08161
08162 if (duration == NULL) {
08163 ast_log(LOG_WARNING, "Error play_record_review called without duration pointer\n");
08164 return -1;
08165 }
08166
08167 if (!outsidecaller)
08168 snprintf(tempfile, sizeof(tempfile), "%s.tmp", recordfile);
08169 else
08170 ast_copy_string(tempfile, recordfile, sizeof(tempfile));
08171
08172 cmd = '3';
08173
08174 while ((cmd >= 0) && (cmd != 't')) {
08175 switch (cmd) {
08176 case '1':
08177 if (!message_exists) {
08178
08179 cmd = '3';
08180 break;
08181 } else {
08182
08183 if (option_verbose > 2)
08184 ast_verbose(VERBOSE_PREFIX_3 "Saving message as is\n");
08185 if (!outsidecaller)
08186 ast_filerename(tempfile, recordfile, NULL);
08187 ast_stream_and_wait(chan, "vm-msgsaved", chan->language, "");
08188 if (!outsidecaller) {
08189 STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms);
08190 DISPOSE(recordfile, -1);
08191 }
08192 cmd = 't';
08193 return res;
08194 }
08195 case '2':
08196
08197 if (option_verbose > 2)
08198 ast_verbose(VERBOSE_PREFIX_3 "Reviewing the message\n");
08199 cmd = ast_stream_and_wait(chan, tempfile, chan->language, AST_DIGIT_ANY);
08200 break;
08201 case '3':
08202 message_exists = 0;
08203
08204 if (recorded == 1) {
08205 if (option_verbose > 2)
08206 ast_verbose(VERBOSE_PREFIX_3 "Re-recording the message\n");
08207 } else {
08208 if (option_verbose > 2)
08209 ast_verbose(VERBOSE_PREFIX_3 "Recording the message\n");
08210 }
08211 if (recorded && outsidecaller) {
08212 cmd = ast_play_and_wait(chan, INTRO);
08213 cmd = ast_play_and_wait(chan, "beep");
08214 }
08215 recorded = 1;
08216
08217 if (record_gain)
08218 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0);
08219 if (ast_test_flag(vmu, VM_OPERATOR))
08220 canceldtmf = "0";
08221 cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf);
08222 if (record_gain)
08223 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &zero_gain, sizeof(zero_gain), 0);
08224 if (cmd == -1) {
08225
08226 if (!outsidecaller) {
08227
08228 ast_filedelete(tempfile, NULL);
08229 }
08230 return cmd;
08231 }
08232 if (cmd == '0') {
08233 break;
08234 } else if (cmd == '*') {
08235 break;
08236 }
08237 #if 0
08238 else if (vmu->review && (*duration < 5)) {
08239
08240 if (option_verbose > 2)
08241 ast_verbose(VERBOSE_PREFIX_3 "Message too short\n");
08242 cmd = ast_play_and_wait(chan, "vm-tooshort");
08243 cmd = ast_filedelete(tempfile, NULL);
08244 break;
08245 }
08246 else if (vmu->review && (cmd == 2 && *duration < (maxsilence + 3))) {
08247
08248 if (option_verbose > 2)
08249 ast_verbose(VERBOSE_PREFIX_3 "Nothing recorded\n");
08250 cmd = ast_filedelete(tempfile, NULL);
08251 cmd = ast_play_and_wait(chan, "vm-nothingrecorded");
08252 if (!cmd)
08253 cmd = ast_play_and_wait(chan, "vm-speakup");
08254 break;
08255 }
08256 #endif
08257 else {
08258
08259 message_exists = 1;
08260 cmd = 0;
08261 }
08262 break;
08263 case '4':
08264 case '5':
08265 case '6':
08266 case '7':
08267 case '8':
08268 case '9':
08269 case '*':
08270 case '#':
08271 cmd = ast_play_and_wait(chan, "vm-sorry");
08272 break;
08273 #if 0
08274
08275
08276 case '*':
08277
08278 cmd = ast_play_and_wait(chan, "vm-deleted");
08279 cmd = ast_filedelete(tempfile, NULL);
08280 if (outsidecaller) {
08281 res = vm_exec(chan, NULL);
08282 return res;
08283 }
08284 else
08285 return 1;
08286 #endif
08287 case '0':
08288 if (!ast_test_flag(vmu, VM_OPERATOR)) {
08289 cmd = ast_play_and_wait(chan, "vm-sorry");
08290 break;
08291 }
08292 if (message_exists || recorded) {
08293 cmd = ast_play_and_wait(chan, "vm-saveoper");
08294 if (!cmd)
08295 cmd = ast_waitfordigit(chan, 3000);
08296 if (cmd == '1') {
08297 ast_play_and_wait(chan, "vm-msgsaved");
08298 cmd = '0';
08299 } else {
08300 ast_play_and_wait(chan, "vm-deleted");
08301 DELETE(recordfile, -1, recordfile);
08302 cmd = '0';
08303 }
08304 }
08305 return cmd;
08306 default:
08307
08308
08309
08310 if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW))
08311 return cmd;
08312 if (message_exists) {
08313 cmd = ast_play_and_wait(chan, "vm-review");
08314 }
08315 else {
08316 cmd = ast_play_and_wait(chan, "vm-torerecord");
08317 if (!cmd)
08318 cmd = ast_waitfordigit(chan, 600);
08319 }
08320
08321 if (!cmd && outsidecaller && ast_test_flag(vmu, VM_OPERATOR)) {
08322 cmd = ast_play_and_wait(chan, "vm-reachoper");
08323 if (!cmd)
08324 cmd = ast_waitfordigit(chan, 600);
08325 }
08326 #if 0
08327 if (!cmd)
08328 cmd = ast_play_and_wait(chan, "vm-tocancelmsg");
08329 #endif
08330 if (!cmd)
08331 cmd = ast_waitfordigit(chan, 6000);
08332 if (!cmd) {
08333 attempts++;
08334 }
08335 if (attempts > max_attempts) {
08336 cmd = 't';
08337 }
08338 }
08339 }
08340 if (outsidecaller)
08341 ast_play_and_wait(chan, "vm-goodbye");
08342 if (cmd == 't')
08343 cmd = 0;
08344 return cmd;
08345 }
08346
08347 #ifdef IMAP_STORAGE
08348
08349 static void write_file(char *filename, char *buffer, unsigned long len)
08350 {
08351 FILE *output;
08352
08353 output = fopen (filename, "w");
08354 fwrite (buffer, len, 1, output);
08355 fclose (output);
08356 }
08357
08358 void mm_searched(MAILSTREAM *stream, unsigned long number)
08359 {
08360 struct vm_state *vms;
08361 char *mailbox;
08362 char *user;
08363 mailbox = stream->mailbox;
08364 user = get_user_by_mailbox(mailbox);
08365 vms = get_vm_state_by_imapuser(user,2);
08366 if (vms) {
08367 if(option_debug > 2)
08368 ast_log (LOG_DEBUG, "saving mailbox message number %lu as message %d. Interactive set to %d\n",number,vms->vmArrayIndex,vms->interactive);
08369 vms->msgArray[vms->vmArrayIndex++] = number;
08370 } else {
08371 ast_log (LOG_ERROR, "No state found.\n");
08372 }
08373 }
08374
08375
08376
08377
08378
08379
08380
08381 static void display_body(BODY *body, char *pfx, long i)
08382 {
08383 char tmp[MAILTMPLEN];
08384 char *s = tmp;
08385 PARAMETER *par;
08386 PART *part;
08387 if (body->type == TYPEMULTIPART) {
08388
08389 if (pfx)
08390 sprintf (tmp, "%s%ld.", pfx, ++i);
08391 else
08392 tmp[0] = '\0';
08393 for (i = 0, part = body->nested.part; part; part = part->next)
08394 display_body (&part->body, tmp, i++);
08395 } else {
08396 if (!pfx)
08397 pfx = "";
08398 sprintf (s, " %s%ld %s", pfx, ++i, body_types[body->type]);
08399 if (body->subtype)
08400 sprintf (s += strlen (s), "/%s", body->subtype);
08401 if (body->description)
08402 sprintf (s += strlen (s), " (%s)", body->description);
08403 if ((par = body->parameter))
08404 do
08405 sprintf (s += strlen (s), ";%s=%s", par->attribute, par->value);
08406 while ((par = par->next));
08407 if (body->id)
08408 sprintf (s += strlen (s), ", id = %s", body->id);
08409 switch (body->type) {
08410 case TYPEMESSAGE:
08411 case TYPETEXT:
08412 sprintf (s += strlen (s), " (%lu lines)", body->size.lines);
08413 break;
08414 default:
08415 sprintf (s += strlen (s), " (%lu bytes)", body->size.bytes);
08416 break;
08417 }
08418
08419
08420 if ((body->type == TYPEMESSAGE) && !strcmp (body->subtype, "RFC822") && (body = body->nested.msg->body)) {
08421 if (body->type == TYPEMULTIPART)
08422 display_body (body, pfx, i - 1);
08423 else {
08424 sprintf (tmp, "%s%ld.", pfx, i);
08425 display_body (body, tmp, (long) 0);
08426 }
08427 }
08428 }
08429 }
08430
08431 #if 0
08432
08433
08434
08435 static void status(MAILSTREAM *stream)
08436 {
08437 unsigned long i;
08438 char *s, date[MAILTMPLEN];
08439 THREADER *thr;
08440 AUTHENTICATOR *auth;
08441 rfc822_date (date);
08442 ast_log (LOG_NOTICE,"%s\n",date);
08443 if (stream) {
08444 if (stream->mailbox)
08445 ast_log (LOG_NOTICE," %s mailbox: %s, %lu messages, %lu recent\n",
08446 stream->dtb->name, stream->mailbox, stream->nmsgs,stream->recent);
08447 else
08448 ast_log (LOG_NOTICE,"No mailbox is open on this stream\n");
08449 if (stream->user_flags[0]) {
08450 ast_log (LOG_NOTICE,"Keywords: %s\n", stream->user_flags[0]);
08451 for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
08452 ast_log (LOG_NOTICE," %s\n", stream->user_flags[i]);
08453 }
08454 if (!strcmp (stream->dtb->name, "imap")) {
08455 if (LEVELIMAP4rev1 (stream))
08456 s = "IMAP4rev1 (RFC 3501)";
08457 else if (LEVEL1730 (stream))
08458 s = "IMAP4 (RFC 1730)";
08459 else if (LEVELIMAP2bis (stream))
08460 s = "IMAP2bis";
08461 else if (LEVEL1176 (stream))
08462 s = "IMAP2 (RFC 1176)";
08463 else
08464 s = "IMAP2 (RFC 1064)";
08465 ast_log (LOG_NOTICE,"%s server %s\n", s, imap_host (stream));
08466 if (LEVELIMAP4 (stream)) {
08467 if ((i = (imap_cap(stream)->auth))) {
08468 s = "";
08469 ast_log (LOG_NOTICE,"Mutually-supported SASL mechanisms:\n");
08470 while ((auth = mail_lookup_auth (find_rightmost_bit (&i) + 1))) {
08471 ast_log (LOG_NOTICE," %s\n", auth->name);
08472 if (!strcmp (auth->name, "PLAIN"))
08473 s = "\n [LOGIN will not be listed here if PLAIN is supported]\n";
08474 }
08475 ast_log (LOG_NOTICE,s);
08476 }
08477 ast_log (LOG_NOTICE,"Supported standard extensions:\n");
08478 if (LEVELACL (stream))
08479 ast_log (LOG_NOTICE," Access Control lists (RFC 2086)\n");
08480 if (LEVELQUOTA (stream))
08481 ast_log (LOG_NOTICE," Quotas (RFC 2087)\n");
08482 if (LEVELLITERALPLUS (stream))
08483 ast_log (LOG_NOTICE," Non-synchronizing literals (RFC 2088)\n");
08484 if (LEVELIDLE (stream))
08485 ast_log (LOG_NOTICE," IDLE unsolicited update (RFC 2177)\n");
08486 if (LEVELMBX_REF (stream))
08487 ast_log (LOG_NOTICE," Mailbox referrals (RFC 2193)\n");
08488 if (LEVELLOG_REF (stream))
08489 ast_log (LOG_NOTICE," Login referrals (RFC 2221)\n");
08490 if (LEVELANONYMOUS (stream))
08491 ast_log (LOG_NOTICE," Anonymous access (RFC 2245)\n");
08492 if (LEVELNAMESPACE (stream))
08493 ast_log (LOG_NOTICE," Multiple namespaces (RFC 2342)\n");
08494 if (LEVELUIDPLUS (stream))
08495 ast_log (LOG_NOTICE," Extended UID behavior (RFC 2359)\n");
08496 if (LEVELSTARTTLS (stream))
08497 ast_log (LOG_NOTICE," Transport Layer Security (RFC 2595)\n");
08498 if (LEVELLOGINDISABLED (stream))
08499 ast_log (LOG_NOTICE," LOGIN command disabled (RFC 2595)\n");
08500 if (LEVELID (stream))
08501 ast_log (LOG_NOTICE," Implementation identity negotiation (RFC 2971)\n");
08502 if (LEVELCHILDREN (stream))
08503 ast_log (LOG_NOTICE," LIST children announcement (RFC 3348)\n");
08504 if (LEVELMULTIAPPEND (stream))
08505 ast_log (LOG_NOTICE," Atomic multiple APPEND (RFC 3502)\n");
08506 if (LEVELBINARY (stream))
08507 ast_log (LOG_NOTICE," Binary body content (RFC 3516)\n");
08508 ast_log (LOG_NOTICE,"Supported draft extensions:\n");
08509 if (LEVELUNSELECT (stream))
08510 ast_log (LOG_NOTICE," Mailbox unselect\n");
08511 if (LEVELSASLIR (stream))
08512 ast_log (LOG_NOTICE," SASL initial client response\n");
08513 if (LEVELSORT (stream))
08514 ast_log (LOG_NOTICE," Server-based sorting\n");
08515 if (LEVELTHREAD (stream)) {
08516 ast_log (LOG_NOTICE," Server-based threading:\n");
08517 for (thr = imap_cap(stream)->threader; thr; thr = thr->next)
08518 ast_log (LOG_NOTICE," %s\n", thr->name);
08519 }
08520 if (LEVELSCAN (stream))
08521 ast_log (LOG_NOTICE," Mailbox text scan\n");
08522 if ((i = imap_cap(stream)->extlevel)) {
08523 ast_log (LOG_NOTICE,"Supported BODYSTRUCTURE extensions:\n");
08524 switch (i) {
08525 case BODYEXTLOC:
08526 ast_log (LOG_NOTICE," location\n");
08527 case BODYEXTLANG:
08528 ast_log (LOG_NOTICE," language\n");
08529 case BODYEXTDSP:
08530 ast_log (LOG_NOTICE," disposition\n");
08531 case BODYEXTMD5:
08532 ast_log (LOG_NOTICE," MD5\n");
08533 }
08534 }
08535 }else
08536 ast_log (LOG_NOTICE,"\n");
08537 }
08538 }
08539 }
08540 #endif
08541
08542 static struct ast_vm_user *find_user_realtime_imapuser(const char *imapuser)
08543 {
08544 struct ast_variable *var;
08545 struct ast_vm_user *vmu;
08546
08547 vmu = ast_calloc(1, sizeof *vmu);
08548 if (!vmu)
08549 return NULL;
08550 ast_set_flag(vmu, VM_ALLOCED);
08551 populate_defaults(vmu);
08552
08553 var = ast_load_realtime("voicemail", "imapuser", imapuser, NULL);
08554 if (var) {
08555 apply_options_full(vmu, var);
08556 ast_variables_destroy(var);
08557 return vmu;
08558 } else {
08559 free(vmu);
08560 return NULL;
08561 }
08562 }
08563
08564
08565
08566 void mm_exists(MAILSTREAM * stream, unsigned long number)
08567 {
08568
08569 if(option_debug > 3)
08570 ast_log (LOG_DEBUG, "Entering EXISTS callback for message %ld\n", number);
08571 if (number == 0) return;
08572 set_update(stream);
08573 }
08574
08575
08576 void mm_expunged(MAILSTREAM * stream, unsigned long number)
08577 {
08578
08579 if(option_debug > 3)
08580 ast_log (LOG_DEBUG, "Entering EXPUNGE callback for message %ld\n", number);
08581 if (number == 0) return;
08582 set_update(stream);
08583 }
08584
08585
08586 void mm_flags(MAILSTREAM * stream, unsigned long number)
08587 {
08588
08589 if(option_debug > 3)
08590 ast_log (LOG_DEBUG, "Entering FLAGS callback for message %ld\n", number);
08591 if (number == 0) return;
08592 set_update(stream);
08593 }
08594
08595
08596 void mm_notify(MAILSTREAM * stream, char *string, long errflg)
08597 {
08598 mm_log (string, errflg);
08599 }
08600
08601
08602 void mm_list(MAILSTREAM * stream, int delim, char *mailbox, long attributes)
08603 {
08604 if (delimiter == '\0') {
08605 ast_mutex_lock(&delimiter_lock);
08606 delimiter = delim;
08607 ast_mutex_unlock(&delimiter_lock);
08608 }
08609 if (option_debug > 4) {
08610 ast_log(LOG_DEBUG, "Delimiter set to %c and mailbox %s\n",delim, mailbox);
08611 if (attributes & LATT_NOINFERIORS)
08612 ast_log(LOG_DEBUG, "no inferiors\n");
08613 if (attributes & LATT_NOSELECT)
08614 ast_log(LOG_DEBUG, "no select\n");
08615 if (attributes & LATT_MARKED)
08616 ast_log(LOG_DEBUG, "marked\n");
08617 if (attributes & LATT_UNMARKED)
08618 ast_log(LOG_DEBUG, "unmarked\n");
08619 }
08620 }
08621
08622
08623 void mm_lsub(MAILSTREAM * stream, int delimiter, char *mailbox, long attributes)
08624 {
08625 if (option_debug > 4) {
08626 ast_log(LOG_DEBUG, "Delimiter set to %c and mailbox %s\n",delimiter, mailbox);
08627 if (attributes & LATT_NOINFERIORS)
08628 ast_log(LOG_DEBUG, "no inferiors\n");
08629 if (attributes & LATT_NOSELECT)
08630 ast_log(LOG_DEBUG, "no select\n");
08631 if (attributes & LATT_MARKED)
08632 ast_log(LOG_DEBUG, "marked\n");
08633 if (attributes & LATT_UNMARKED)
08634 ast_log(LOG_DEBUG, "unmarked\n");
08635 }
08636 }
08637
08638
08639 void mm_status(MAILSTREAM * stream, char *mailbox, MAILSTATUS * status)
08640 {
08641 ast_log (LOG_NOTICE," Mailbox %s", mailbox);
08642 if (status->flags & SA_MESSAGES)
08643 ast_log (LOG_NOTICE,", %lu messages", status->messages);
08644 if (status->flags & SA_RECENT)
08645 ast_log (LOG_NOTICE,", %lu recent", status->recent);
08646 if (status->flags & SA_UNSEEN)
08647 ast_log (LOG_NOTICE,", %lu unseen", status->unseen);
08648 if (status->flags & SA_UIDVALIDITY)
08649 ast_log (LOG_NOTICE,", %lu UID validity", status->uidvalidity);
08650 if (status->flags & SA_UIDNEXT)
08651 ast_log (LOG_NOTICE,", %lu next UID", status->uidnext);
08652 ast_log (LOG_NOTICE,"\n");
08653 }
08654
08655
08656 void mm_log(char *string, long errflg)
08657 {
08658 switch ((short) errflg) {
08659 case NIL:
08660 if(option_debug)
08661 ast_log(LOG_DEBUG,"IMAP Info: %s\n", string);
08662 break;
08663 case PARSE:
08664 case WARN:
08665 ast_log (LOG_WARNING,"IMAP Warning: %s\n", string);
08666 break;
08667 case ERROR:
08668 ast_log (LOG_ERROR,"IMAP Error: %s\n", string);
08669 break;
08670 }
08671 }
08672
08673
08674 void mm_dlog(char *string)
08675 {
08676 ast_log (LOG_NOTICE, "%s\n", string);
08677 }
08678
08679
08680 void mm_login(NETMBX * mb, char *user, char *pwd, long trial)
08681 {
08682 struct ast_vm_user *vmu;
08683
08684 if(option_debug > 3)
08685 ast_log(LOG_DEBUG, "Entering callback mm_login\n");
08686
08687 ast_copy_string(user, mb->user, MAILTMPLEN);
08688
08689
08690 if (!ast_strlen_zero(authpassword)) {
08691 ast_copy_string(pwd, authpassword, MAILTMPLEN);
08692 } else {
08693 AST_LIST_TRAVERSE(&users, vmu, list) {
08694 if(!strcasecmp(mb->user, vmu->imapuser)) {
08695 ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
08696 break;
08697 }
08698 }
08699 if (!vmu) {
08700 if ((vmu = find_user_realtime_imapuser(mb->user))) {
08701 ast_copy_string(pwd, vmu->imappassword, MAILTMPLEN);
08702 free_user(vmu);
08703 }
08704 }
08705 }
08706 }
08707
08708
08709 void mm_critical(MAILSTREAM * stream)
08710 {
08711 }
08712
08713
08714 void mm_nocritical(MAILSTREAM * stream)
08715 {
08716 }
08717
08718
08719 long mm_diskerror(MAILSTREAM * stream, long errcode, long serious)
08720 {
08721 kill (getpid (), SIGSTOP);
08722 return NIL;
08723 }
08724
08725
08726 void mm_fatal(char *string)
08727 {
08728 ast_log(LOG_ERROR,"IMAP access FATAL error: %s\n", string);
08729 }
08730
08731
08732 static void mm_parsequota(MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota)
08733 {
08734 struct vm_state *vms;
08735 char *mailbox;
08736 char *user;
08737 unsigned long usage = 0;
08738 unsigned long limit = 0;
08739
08740 while (pquota) {
08741 usage = pquota->usage;
08742 limit = pquota->limit;
08743 pquota = pquota->next;
08744 }
08745
08746 mailbox = stream->mailbox;
08747 user = get_user_by_mailbox(mailbox);
08748 vms = get_vm_state_by_imapuser(user,2);
08749 if (vms) {
08750 if(option_debug > 2)
08751 ast_log (LOG_DEBUG, "User %s usage is %lu, limit is %lu\n",user,usage,limit);
08752 vms->quota_usage = usage;
08753 vms->quota_limit = limit;
08754 } else {
08755 ast_log (LOG_ERROR, "No state found.\n");
08756 }
08757 }
08758
08759 static char *get_header_by_tag(char *header, char *tag)
08760 {
08761 char *start;
08762 int taglen;
08763 char *eol_pnt;
08764
08765 if (!header || !tag)
08766 return NULL;
08767
08768 taglen = strlen(tag) + 1;
08769 if (taglen < 1)
08770 return NULL;
08771
08772 start = strstr(header, tag);
08773 if (!start)
08774 return NULL;
08775
08776 ast_mutex_lock(&imaptemp_lock);
08777 ast_copy_string(imaptemp, start+taglen, sizeof(imaptemp));
08778 ast_mutex_unlock(&imaptemp_lock);
08779 eol_pnt = strchr(imaptemp,'\n');
08780 *eol_pnt = '\0';
08781 return imaptemp;
08782 }
08783
08784 static char *get_user_by_mailbox(char *mailbox)
08785 {
08786 char *start, *quote;
08787 char *eol_pnt;
08788
08789 if (!mailbox)
08790 return NULL;
08791
08792 start = strstr(mailbox,"/user=");
08793 if (!start)
08794 return NULL;
08795
08796 ast_mutex_lock(&imaptemp_lock);
08797 ast_copy_string(imaptemp, start+6, sizeof(imaptemp));
08798 ast_mutex_unlock(&imaptemp_lock);
08799
08800 quote = strchr(imaptemp,'\"');
08801 if (!quote) {
08802 eol_pnt = strchr(imaptemp,'/');
08803 if (!eol_pnt) {
08804 eol_pnt = strchr(imaptemp,'}');
08805 }
08806 *eol_pnt = '\0';
08807 return imaptemp;
08808 } else {
08809 eol_pnt = strchr(imaptemp+1,'\"');
08810 *eol_pnt = '\0';
08811 return imaptemp+1;
08812 }
08813 }
08814
08815 static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive)
08816 {
08817 struct vmstate *vlist = NULL;
08818
08819 vlist = vmstates;
08820 while (vlist) {
08821 if (vlist->vms) {
08822 if (vlist->vms->imapuser) {
08823 if (!strcmp(vlist->vms->imapuser,user)) {
08824 if (interactive == 2) {
08825 return vlist->vms;
08826 } else if (vlist->vms->interactive == interactive) {
08827 return vlist->vms;
08828 }
08829 }
08830 } else {
08831 if(option_debug > 2)
08832 ast_log(LOG_DEBUG, " error: imapuser is NULL for %s\n",user);
08833 }
08834 } else {
08835 if(option_debug > 2)
08836 ast_log(LOG_DEBUG, " error: vms is NULL for %s\n",user);
08837 }
08838 vlist = vlist->next;
08839 }
08840 if(option_debug > 2)
08841 ast_log(LOG_DEBUG, "%s not found in vmstates\n",user);
08842 return NULL;
08843 }
08844
08845 static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, int interactive)
08846 {
08847 struct vmstate *vlist = NULL;
08848
08849 vlist = vmstates;
08850 if(option_debug > 2)
08851 ast_log(LOG_DEBUG, "Mailbox set to %s\n",mailbox);
08852 while (vlist) {
08853 if (vlist->vms) {
08854 if (vlist->vms->username) {
08855 if(option_debug > 2)
08856 ast_log(LOG_DEBUG, " comparing mailbox %s (i=%d) to vmstate mailbox %s (i=%d)\n",mailbox,interactive,vlist->vms->username,vlist->vms->interactive);
08857 if (!strcmp(vlist->vms->username,mailbox) && vlist->vms->interactive == interactive) {
08858 if(option_debug > 2)
08859 ast_log(LOG_DEBUG, " Found it!\n");
08860 return vlist->vms;
08861 }
08862 } else {
08863 if(option_debug > 2)
08864 ast_log(LOG_DEBUG, " error: username is NULL for %s\n",mailbox);
08865 }
08866 } else {
08867 if(option_debug > 2)
08868 ast_log(LOG_DEBUG, " error: vms is NULL for %s\n",mailbox);
08869 }
08870 vlist = vlist->next;
08871 }
08872 if(option_debug > 2)
08873 ast_log(LOG_DEBUG, "%s not found in vmstates\n",mailbox);
08874 return NULL;
08875 }
08876
08877 static void vmstate_insert(struct vm_state *vms)
08878 {
08879 struct vmstate *v;
08880 struct vm_state *altvms;
08881
08882
08883
08884
08885 if (vms->interactive == 1) {
08886 altvms = get_vm_state_by_mailbox(vms->username,0);
08887 if (altvms) {
08888 if(option_debug > 2)
08889 ast_log(LOG_DEBUG, "Duplicate mailbox %s, copying message info...\n",vms->username);
08890 vms->newmessages = altvms->newmessages;
08891 vms->oldmessages = altvms->oldmessages;
08892 if(option_debug > 2)
08893 ast_log(LOG_DEBUG, "check_msgArray before memcpy\n");
08894 check_msgArray(vms);
08895
08896 copy_msgArray(vms, altvms);
08897 if(option_debug > 2)
08898 ast_log(LOG_DEBUG, "check_msgArray after memcpy\n");
08899 check_msgArray(vms);
08900 vms->vmArrayIndex = altvms->vmArrayIndex;
08901 vms->lastmsg = altvms->lastmsg;
08902 vms->curmsg = altvms->curmsg;
08903
08904 vms->persist_vms = altvms;
08905
08906 vms->mailstream = altvms->mailstream;
08907
08908 }
08909 }
08910
08911 v = (struct vmstate *)malloc(sizeof(struct vmstate));
08912 if (!v) {
08913 ast_log(LOG_ERROR, "Out of memory\n");
08914 }
08915 if(option_debug > 2)
08916 ast_log(LOG_DEBUG, "Inserting vm_state for user:%s, mailbox %s\n",vms->imapuser,vms->username);
08917 ast_mutex_lock(&vmstate_lock);
08918 v->vms = vms;
08919 v->next = vmstates;
08920 vmstates = v;
08921 ast_mutex_unlock(&vmstate_lock);
08922 }
08923
08924 static void vmstate_delete(struct vm_state *vms)
08925 {
08926 struct vmstate *vc, *vf = NULL, *vl = NULL;
08927 struct vm_state *altvms;
08928
08929
08930
08931 if (vms->interactive == 1) {
08932 altvms = vms->persist_vms;
08933 if (altvms) {
08934 if(option_debug > 2)
08935 ast_log(LOG_DEBUG, "Duplicate mailbox %s, copying message info...\n",vms->username);
08936 altvms->newmessages = vms->newmessages;
08937 altvms->oldmessages = vms->oldmessages;
08938 altvms->updated = 1;
08939 }
08940 }
08941
08942 ast_mutex_lock(&vmstate_lock);
08943 vc = vmstates;
08944 if(option_debug > 2)
08945 ast_log(LOG_DEBUG, "Removing vm_state for user:%s, mailbox %s\n",vms->imapuser,vms->username);
08946 while (vc) {
08947 if (vc->vms == vms) {
08948 vf = vc;
08949 if (vl)
08950 vl->next = vc->next;
08951 else
08952 vmstates = vc->next;
08953 break;
08954 }
08955 vl = vc;
08956 vc = vc->next;
08957 }
08958 if (!vf) {
08959 ast_log(LOG_ERROR, "No vmstate found for user:%s, mailbox %s\n",vms->imapuser,vms->username);
08960 } else {
08961 free(vf);
08962 }
08963 ast_mutex_unlock(&vmstate_lock);
08964 }
08965
08966 static void set_update(MAILSTREAM * stream)
08967 {
08968 struct vm_state *vms;
08969 char *mailbox;
08970 char *user;
08971
08972 mailbox = stream->mailbox;
08973 user = get_user_by_mailbox(mailbox);
08974 vms = get_vm_state_by_imapuser(user, 0);
08975 if (vms) {
08976 if(option_debug > 2)
08977 ast_log (LOG_DEBUG, "User %s mailbox set for update.\n",user);
08978 vms->updated = 1;
08979 } else {
08980 if(option_debug > 2)
08981 ast_log (LOG_WARNING, "User %s mailbox not found for update.\n",user);
08982 }
08983 }
08984
08985 static void init_vm_state(struct vm_state *vms)
08986 {
08987 int x;
08988 vms->vmArrayIndex = 0;
08989 for (x = 0; x < 256; x++) {
08990 vms->msgArray[x] = 0;
08991 }
08992 }
08993
08994 static void check_msgArray(struct vm_state *vms)
08995 {
08996 int x;
08997 for (x = 0; x<256; x++) {
08998 if (vms->msgArray[x]!=0) {
08999 if(option_debug)
09000 ast_log (LOG_DEBUG, "Item %d set to %ld\n",x,vms->msgArray[x]);
09001 }
09002 }
09003 }
09004
09005 static void copy_msgArray(struct vm_state *dst, struct vm_state *src)
09006 {
09007 int x;
09008 for (x = 0; x<256; x++) {
09009 dst->msgArray[x] = src->msgArray[x];
09010 }
09011 }
09012
09013 static int save_body(BODY *body, struct vm_state *vms, char *section, char *format)
09014 {
09015 char *body_content;
09016 char *body_decoded;
09017 unsigned long len;
09018 unsigned long newlen;
09019 char filename[256];
09020
09021 if (!body || body == NIL)
09022 return -1;
09023 display_body (body, NIL, (long) 0);
09024 body_content = mail_fetchbody (vms->mailstream, vms->msgArray[vms->curmsg], section, &len);
09025 if (body_content != NIL) {
09026 sprintf(filename,"%s.%s", vms->fn, format);
09027
09028 body_decoded = rfc822_base64 ((unsigned char *)body_content, len, &newlen);
09029 write_file (filename, (char *) body_decoded, newlen);
09030 }
09031 return 0;
09032 }
09033
09034
09035 static void get_mailbox_delimiter(MAILSTREAM *stream) {
09036 char tmp[50];
09037 sprintf(tmp, "{%s}", imapserver);
09038 mail_list(stream, tmp, "*");
09039 }
09040
09041 #endif
09042
09043
09044
09045
09046
09047 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
09048 .load = load_module,
09049 .unload = unload_module,
09050 .reload = reload,
09051 );