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