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