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: 152463 $")
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 #ifdef USE_SYSTEM_IMAP
00074 #include <imap/c-client.h>
00075 #include <imap/imap4r1.h>
00076 #include <imap/linkage.h>
00077 #elif defined (USE_SYSTEM_CCLIENT)
00078 #include <c-client/c-client.h>
00079 #include <c-client/imap4r1.h>
00080 #include <c-client/linkage.h>
00081 #else
00082 #include "c-client.h"
00083 #include "imap4r1.h"
00084 #include "linkage.h"
00085 #endif
00086 #endif
00087 #include "asterisk/lock.h"
00088 #include "asterisk/file.h"
00089 #include "asterisk/logger.h"
00090 #include "asterisk/channel.h"
00091 #include "asterisk/pbx.h"
00092 #include "asterisk/options.h"
00093 #include "asterisk/config.h"
00094 #include "asterisk/say.h"
00095 #include "asterisk/module.h"
00096 #include "asterisk/adsi.h"
00097 #include "asterisk/app.h"
00098 #include "asterisk/manager.h"
00099 #include "asterisk/dsp.h"
00100 #include "asterisk/localtime.h"
00101 #include "asterisk/cli.h"
00102 #include "asterisk/utils.h"
00103 #include "asterisk/stringfields.h"
00104 #include "asterisk/smdi.h"
00105 #ifdef ODBC_STORAGE
00106 #include "asterisk/res_odbc.h"
00107 #endif
00108
00109 #ifdef IMAP_STORAGE
00110 AST_MUTEX_DEFINE_STATIC(imaptemp_lock);
00111 static char imaptemp[1024];
00112 static char imapserver[48];
00113 static char imapport[8];
00114 static char imapflags[128];
00115 static char imapfolder[64];
00116 static char authuser[32];
00117 static char authpassword[42];
00118
00119 static int expungeonhangup = 1;
00120 static char delimiter = '\0';
00121 static const long DEFAULT_IMAP_TCP_TIMEOUT = 60L;
00122
00123 struct vm_state;
00124 struct ast_vm_user;
00125
00126 static int init_mailstream (struct vm_state *vms, int box);
00127 static void write_file (char *filename, char *buffer, unsigned long len);
00128
00129 static char *get_header_by_tag(char *header, char *tag);
00130 static void vm_imap_delete(int msgnum, struct ast_vm_user *vmu);
00131 static char *get_user_by_mailbox(char *mailbox);
00132 static struct vm_state *get_vm_state_by_imapuser(char *user, int interactive);
00133 static struct vm_state *get_vm_state_by_mailbox(const char *mailbox, const char *context, int interactive);
00134 static struct vm_state *create_vm_state_from_user(struct ast_vm_user *vmu);
00135 static void vmstate_insert(struct vm_state *vms);
00136 static void vmstate_delete(struct vm_state *vms);
00137 static void set_update(MAILSTREAM * stream);
00138 static void init_vm_state(struct vm_state *vms);
00139 static void copy_msgArray(struct vm_state *dst, struct vm_state *src);
00140 static int save_body(BODY *body, struct vm_state *vms, char *section, char *format);
00141 static void get_mailbox_delimiter(MAILSTREAM *stream);
00142 static void mm_parsequota (MAILSTREAM *stream, unsigned char *msg, QUOTALIST *pquota);
00143 static void imap_mailbox_name(char *spec, size_t len, struct vm_state *vms, int box, int target);
00144 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);
00145 static void check_quota(struct vm_state *vms, char *mailbox);
00146 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box);
00147 struct vmstate {
00148 struct vm_state *vms;
00149 struct vmstate *next;
00150 };
00151 AST_MUTEX_DEFINE_STATIC(vmstate_lock);
00152 static struct vmstate *vmstates = NULL;
00153 #endif
00154
00155 #define SMDI_MWI_WAIT_TIMEOUT 1000
00156
00157 #define COMMAND_TIMEOUT 5000
00158
00159 #define VOICEMAIL_DIR_MODE 0777
00160 #define VOICEMAIL_FILE_MODE 0666
00161 #define CHUNKSIZE 65536
00162
00163 #define VOICEMAIL_CONFIG "voicemail.conf"
00164 #define ASTERISK_USERNAME "asterisk"
00165
00166
00167
00168 #define SENDMAIL "/usr/sbin/sendmail -t"
00169
00170 #define INTRO "vm-intro"
00171
00172 #define MAXMSG 100
00173 #ifndef IMAP_STORAGE
00174 #define MAXMSGLIMIT 9999
00175 #else
00176 #define MAXMSGLIMIT 255
00177 #endif
00178
00179 #define BASEMAXINLINE 256
00180 #define BASELINELEN 72
00181 #define BASEMAXINLINE 256
00182 #define eol "\r\n"
00183
00184 #define MAX_DATETIME_FORMAT 512
00185 #define MAX_NUM_CID_CONTEXTS 10
00186
00187 #define VM_REVIEW (1 << 0)
00188 #define VM_OPERATOR (1 << 1)
00189 #define VM_SAYCID (1 << 2)
00190 #define VM_SVMAIL (1 << 3)
00191 #define VM_ENVELOPE (1 << 4)
00192 #define VM_SAYDURATION (1 << 5)
00193 #define VM_SKIPAFTERCMD (1 << 6)
00194 #define VM_FORCENAME (1 << 7)
00195 #define VM_FORCEGREET (1 << 8)
00196 #define VM_PBXSKIP (1 << 9)
00197 #define VM_DIRECFORWARD (1 << 10)
00198 #define VM_ATTACH (1 << 11)
00199 #define VM_DELETE (1 << 12)
00200 #define VM_ALLOCED (1 << 13)
00201 #define VM_SEARCH (1 << 14)
00202 #define VM_TEMPGREETWARN (1 << 15)
00203 #define ERROR_LOCK_PATH -100
00204 #define ERROR_MAILBOX_FULL -200
00205
00206
00207 enum {
00208 OPT_SILENT = (1 << 0),
00209 OPT_BUSY_GREETING = (1 << 1),
00210 OPT_UNAVAIL_GREETING = (1 << 2),
00211 OPT_RECORDGAIN = (1 << 3),
00212 OPT_PREPEND_MAILBOX = (1 << 4),
00213 OPT_PRIORITY_JUMP = (1 << 5),
00214 OPT_AUTOPLAY = (1 << 6),
00215 } vm_option_flags;
00216
00217 enum {
00218 OPT_ARG_RECORDGAIN = 0,
00219 OPT_ARG_PLAYFOLDER = 1,
00220
00221 OPT_ARG_ARRAY_SIZE = 2,
00222 } vm_option_args;
00223
00224 AST_APP_OPTIONS(vm_app_options, {
00225 AST_APP_OPTION('s', OPT_SILENT),
00226 AST_APP_OPTION('b', OPT_BUSY_GREETING),
00227 AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
00228 AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
00229 AST_APP_OPTION('p', OPT_PREPEND_MAILBOX),
00230 AST_APP_OPTION('j', OPT_PRIORITY_JUMP),
00231 AST_APP_OPTION_ARG('a', OPT_AUTOPLAY, OPT_ARG_PLAYFOLDER),
00232 });
00233
00234 static int load_config(void);
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 struct baseio {
00323 int iocp;
00324 int iolen;
00325 int linelength;
00326 int ateof;
00327 unsigned char iobuf[BASEMAXINLINE];
00328 };
00329
00330
00331 struct ast_vm_user {
00332 char context[AST_MAX_CONTEXT];
00333 char mailbox[AST_MAX_EXTENSION];
00334 char password[80];
00335 char fullname[80];
00336 char email[80];
00337 char pager[80];
00338 char serveremail[80];
00339 char mailcmd[160];
00340 char language[MAX_LANGUAGE];
00341 char zonetag[80];
00342 char callback[80];
00343 char dialout[80];
00344 char uniqueid[80];
00345 char exit[80];
00346 char attachfmt[20];
00347 unsigned int flags;
00348 int saydurationm;
00349 int maxmsg;
00350 #ifdef IMAP_STORAGE
00351 char imapuser[80];
00352 char imappassword[80];
00353 #endif
00354 double volgain;
00355 AST_LIST_ENTRY(ast_vm_user) list;
00356 };
00357
00358 struct vm_zone {
00359 AST_LIST_ENTRY(vm_zone) list;
00360 char name[80];
00361 char timezone[80];
00362 char msg_format[512];
00363 };
00364
00365 struct vm_state {
00366 char curbox[80];
00367 char username[80];
00368 char context[80];
00369 char curdir[PATH_MAX];
00370 char vmbox[PATH_MAX];
00371 char fn[PATH_MAX];
00372 char fn2[PATH_MAX];
00373 int *deleted;
00374 int *heard;
00375 int curmsg;
00376 int lastmsg;
00377 int newmessages;
00378 int oldmessages;
00379 int starting;
00380 int repeats;
00381 #ifdef IMAP_STORAGE
00382 ast_mutex_t lock;
00383 int updated;
00384 long msgArray[256];
00385 MAILSTREAM *mailstream;
00386 int vmArrayIndex;
00387 char imapuser[80];
00388 int interactive;
00389 unsigned int quota_limit;
00390 unsigned int quota_usage;
00391 struct vm_state *persist_vms;
00392 #endif
00393 };
00394 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);
00395 static int dialout(struct ast_channel *chan, struct ast_vm_user *vmu, char *num, char *outgoing_context);
00396 static int play_record_review(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime,
00397 char *fmt, int outsidecaller, struct ast_vm_user *vmu, int *duration, const char *unlockdir,
00398 signed char record_gain, struct vm_state *vms);
00399 static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain);
00400 static int vm_play_folder_name(struct ast_channel *chan, char *mbox);
00401 static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname);
00402 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);
00403 #if !(defined(ODBC_STORAGE) || defined(IMAP_STORAGE))
00404 static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit);
00405 #endif
00406 static void apply_options(struct ast_vm_user *vmu, const char *options);
00407
00408 #ifdef ODBC_STORAGE
00409 static char odbc_database[80];
00410 static char odbc_table[80];
00411 #define RETRIEVE(a,b,c) retrieve_file(a,b)
00412 #define DISPOSE(a,b) remove_file(a,b)
00413 #define STORE(a,b,c,d,e,f,g,h,i) store_file(a,b,c,d)
00414 #define EXISTS(a,b,c,d) (message_exists(a,b))
00415 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f))
00416 #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f))
00417 #define DELETE(a,b,c,d) (delete_file(a,b))
00418 #else
00419 #ifdef IMAP_STORAGE
00420 #define RETRIEVE(a,b,c) imap_retrieve_file(a,b,c)
00421 #define DISPOSE(a,b) remove_file(a,b)
00422 #define STORE(a,b,c,d,e,f,g,h,i) (imap_store_file(a,b,c,d,e,f,g,h,i))
00423 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00424 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00425 #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h));
00426 #define DELETE(a,b,c,d) (vm_imap_delete(b,d))
00427 #else
00428 #define RETRIEVE(a,b,c)
00429 #define DISPOSE(a,b)
00430 #define STORE(a,b,c,d,e,f,g,h,i)
00431 #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0)
00432 #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h));
00433 #define COPY(a,b,c,d,e,f,g,h) (copy_plain_file(g,h));
00434 #define DELETE(a,b,c,d) (vm_delete(c))
00435 #endif
00436 #endif
00437
00438 static char VM_SPOOL_DIR[PATH_MAX];
00439
00440 static char ext_pass_cmd[128];
00441
00442 int my_umask;
00443
00444 #if ODBC_STORAGE
00445 #define tdesc "Comedian Mail (Voicemail System) with ODBC Storage"
00446 #elif IMAP_STORAGE
00447 #define tdesc "Comedian Mail (Voicemail System) with IMAP Storage"
00448 #else
00449 #define tdesc "Comedian Mail (Voicemail System)"
00450 #endif
00451
00452 static char userscontext[AST_MAX_EXTENSION] = "default";
00453
00454 static char *addesc = "Comedian Mail";
00455
00456 static char *synopsis_vm =
00457 "Leave a Voicemail message";
00458
00459 static char *descrip_vm =
00460 " VoiceMail(mailbox[@context][&mailbox[@context]][...][|options]): This\n"
00461 "application allows the calling party to leave a message for the specified\n"
00462 "list of mailboxes. When multiple mailboxes are specified, the greeting will\n"
00463 "be taken from the first mailbox specified. Dialplan execution will stop if the\n"
00464 "specified mailbox does not exist.\n"
00465 " The Voicemail application will exit if any of the following DTMF digits are\n"
00466 "received:\n"
00467 " 0 - Jump to the 'o' extension in the current dialplan context.\n"
00468 " * - Jump to the 'a' extension in the current dialplan context.\n"
00469 " This application will set the following channel variable upon completion:\n"
00470 " VMSTATUS - This indicates the status of the execution of the VoiceMail\n"
00471 " application. The possible values are:\n"
00472 " SUCCESS | USEREXIT | FAILED\n\n"
00473 " Options:\n"
00474 " b - Play the 'busy' greeting to the calling party.\n"
00475 " g(#) - Use the specified amount of gain when recording the voicemail\n"
00476 " message. The units are whole-number decibels (dB).\n"
00477 " Only works on supported technologies, which is Zap only.\n"
00478 " s - Skip the playback of instructions for leaving a message to the\n"
00479 " calling party.\n"
00480 " u - Play the 'unavailable' greeting.\n"
00481 " j - Jump to priority n+101 if the mailbox is not found or some other\n"
00482 " error occurs.\n";
00483
00484 static char *synopsis_vmain =
00485 "Check Voicemail messages";
00486
00487 static char *descrip_vmain =
00488 " VoiceMailMain([mailbox][@context][|options]): This application allows the\n"
00489 "calling party to check voicemail messages. A specific mailbox, and optional\n"
00490 "corresponding context, may be specified. If a mailbox is not provided, the\n"
00491 "calling party will be prompted to enter one. If a context is not specified,\n"
00492 "the 'default' context will be used.\n\n"
00493 " Options:\n"
00494 " p - Consider the mailbox parameter as a prefix to the mailbox that\n"
00495 " is entered by the caller.\n"
00496 " g(#) - Use the specified amount of gain when recording a voicemail\n"
00497 " message. The units are whole-number decibels (dB).\n"
00498 " s - Skip checking the passcode for the mailbox.\n"
00499 " a(#) - Skip folder prompt and go directly to folder specified.\n"
00500 " Defaults to INBOX\n";
00501
00502 static char *synopsis_vm_box_exists =
00503 "Check to see if Voicemail mailbox exists";
00504
00505 static char *descrip_vm_box_exists =
00506 " MailboxExists(mailbox[@context][|options]): Check to see if the specified\n"
00507 "mailbox exists. If no voicemail context is specified, the 'default' context\n"
00508 "will be used.\n"
00509 " This application will set the following channel variable upon completion:\n"
00510 " VMBOXEXISTSSTATUS - This will contain the status of the execution of the\n"
00511 " MailboxExists application. Possible values include:\n"
00512 " SUCCESS | FAILED\n\n"
00513 " Options:\n"
00514 " j - Jump to priority n+101 if the mailbox is found.\n";
00515
00516 static char *synopsis_vmauthenticate =
00517 "Authenticate with Voicemail passwords";
00518
00519 static char *descrip_vmauthenticate =
00520 " VMAuthenticate([mailbox][@context][|options]): This application behaves the\n"
00521 "same way as the Authenticate application, but the passwords are taken from\n"
00522 "voicemail.conf.\n"
00523 " If the mailbox is specified, only that mailbox's password will be considered\n"
00524 "valid. If the mailbox is not specified, the channel variable AUTH_MAILBOX will\n"
00525 "be set with the authenticated mailbox.\n\n"
00526 " Options:\n"
00527 " s - Skip playing the initial prompts.\n";
00528
00529
00530 static char *app = "VoiceMail";
00531
00532
00533 static char *app2 = "VoiceMailMain";
00534
00535 static char *app3 = "MailboxExists";
00536 static char *app4 = "VMAuthenticate";
00537
00538 static AST_LIST_HEAD_STATIC(users, ast_vm_user);
00539 static AST_LIST_HEAD_STATIC(zones, vm_zone);
00540 static int maxsilence;
00541 static int maxmsg;
00542 static int silencethreshold = 128;
00543 static char serveremail[80];
00544 static char mailcmd[160];
00545 static char externnotify[160];
00546 static struct ast_smdi_interface *smdi_iface = NULL;
00547 static char vmfmts[80];
00548 static double volgain;
00549 static int vmminmessage;
00550 static int vmmaxmessage;
00551 static int maxgreet;
00552 static int skipms;
00553 static int maxlogins;
00554
00555 static struct ast_flags globalflags = {0};
00556
00557 static int saydurationminfo;
00558
00559 static char dialcontext[AST_MAX_CONTEXT];
00560 static char callcontext[AST_MAX_CONTEXT];
00561 static char exitcontext[AST_MAX_CONTEXT];
00562
00563 static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
00564
00565
00566 static char *emailbody = NULL;
00567 static char *emailsubject = NULL;
00568 static char *pagerbody = NULL;
00569 static char *pagersubject = NULL;
00570 static char fromstring[100];
00571 static char pagerfromstring[100];
00572 static char emailtitle[100];
00573 static char charset[32] = "ISO-8859-1";
00574
00575 static unsigned char adsifdn[4] = "\x00\x00\x00\x0F";
00576 static unsigned char adsisec[4] = "\x9B\xDB\xF7\xAC";
00577 static int adsiver = 1;
00578 static char emaildateformat[32] = "%A, %B %d, %Y at %r";
00579
00580
00581 static char *strip_control(const char *input, char *buf, size_t buflen)
00582 {
00583 char *bufptr = buf;
00584 for (; *input; input++) {
00585 if (*input < 32) {
00586 continue;
00587 }
00588 *bufptr++ = *input;
00589 if (bufptr == buf + buflen - 1) {
00590 break;
00591 }
00592 }
00593 *bufptr = '\0';
00594 return buf;
00595 }
00596
00597 static void populate_defaults(struct ast_vm_user *vmu)
00598 {
00599 ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
00600 if (saydurationminfo)
00601 vmu->saydurationm = saydurationminfo;
00602 ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
00603 ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
00604 ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
00605 if (maxmsg)
00606 vmu->maxmsg = maxmsg;
00607 vmu->volgain = volgain;
00608 }
00609
00610 static void apply_option(struct ast_vm_user *vmu, const char *var, const char *value)
00611 {
00612 int x;
00613 if (!strcasecmp(var, "attach")) {
00614 ast_set2_flag(vmu, ast_true(value), VM_ATTACH);
00615 } else if (!strcasecmp(var, "attachfmt")) {
00616 ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
00617 } else if (!strcasecmp(var, "serveremail")) {
00618 ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
00619 } else if (!strcasecmp(var, "language")) {
00620 ast_copy_string(vmu->language, value, sizeof(vmu->language));
00621 } else if (!strcasecmp(var, "tz")) {
00622 ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag));
00623 #ifdef IMAP_STORAGE
00624 } else if (!strcasecmp(var, "imapuser")) {
00625 ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser));
00626 } else if (!strcasecmp(var, "imappassword") || !strcasecmp(var, "imapsecret")) {
00627 ast_copy_string(vmu->imappassword, value, sizeof(vmu->imappassword));
00628 #endif
00629 } else if (!strcasecmp(var, "delete") || !strcasecmp(var, "deletevoicemail")) {
00630 ast_set2_flag(vmu, ast_true(value), VM_DELETE);
00631 } else if (!strcasecmp(var, "saycid")){
00632 ast_set2_flag(vmu, ast_true(value), VM_SAYCID);
00633 } else if (!strcasecmp(var,"sendvoicemail")){
00634 ast_set2_flag(vmu, ast_true(value), VM_SVMAIL);
00635 } else if (!strcasecmp(var, "review")){
00636 ast_set2_flag(vmu, ast_true(value), VM_REVIEW);
00637 } else if (!strcasecmp(var, "tempgreetwarn")){
00638 ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN);
00639 } else if (!strcasecmp(var, "operator")){
00640 ast_set2_flag(vmu, ast_true(value), VM_OPERATOR);
00641 } else if (!strcasecmp(var, "envelope")){
00642 ast_set2_flag(vmu, ast_true(value), VM_ENVELOPE);
00643 } else if (!strcasecmp(var, "sayduration")){
00644 ast_set2_flag(vmu, ast_true(value), VM_SAYDURATION);
00645 } else if (!strcasecmp(var, "saydurationm")){
00646 if (sscanf(value, "%d", &x) == 1) {
00647 vmu->saydurationm = x;
00648 } else {
00649 ast_log(LOG_WARNING, "Invalid min duration for say duration\n");
00650 }
00651 } else if (!strcasecmp(var, "forcename")){
00652 ast_set2_flag(vmu, ast_true(value), VM_FORCENAME);
00653 } else if (!strcasecmp(var, "forcegreetings")){
00654 ast_set2_flag(vmu, ast_true(value), VM_FORCEGREET);
00655 } else if (!strcasecmp(var, "callback")) {
00656 ast_copy_string(vmu->callback, value, sizeof(vmu->callback));
00657 } else if (!strcasecmp(var, "dialout")) {
00658 ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
00659 } else if (!strcasecmp(var, "exitcontext")) {
00660 ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
00661 } else if (!strcasecmp(var, "maxmsg")) {
00662 vmu->maxmsg = atoi(value);
00663 if (vmu->maxmsg <= 0) {
00664 ast_log(LOG_WARNING, "Invalid number of messages per folder maxmsg=%s. Using default value %i\n", value, MAXMSG);
00665 vmu->maxmsg = MAXMSG;
00666 } else if (vmu->maxmsg > MAXMSGLIMIT) {
00667 ast_log(LOG_WARNING, "Maximum number of messages per folder is %i. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
00668 vmu->maxmsg = MAXMSGLIMIT;
00669 }
00670 } else if (!strcasecmp(var, "volgain")) {
00671 sscanf(value, "%lf", &vmu->volgain);
00672 } else if (!strcasecmp(var, "options")) {
00673 apply_options(vmu, value);
00674 }
00675 }
00676
00677 static int change_password_realtime(struct ast_vm_user *vmu, const char *password)
00678 {
00679 int res;
00680 if (!ast_strlen_zero(vmu->uniqueid)) {
00681 res = ast_update_realtime("voicemail", "uniqueid", vmu->uniqueid, "password", password, NULL);
00682 if (res > 0) {
00683 ast_copy_string(vmu->password, password, sizeof(vmu->password));
00684 res = 0;
00685 } else if (!res) {
00686 res = -1;
00687 }
00688 return res;
00689 }
00690 return -1;
00691 }
00692
00693 static void apply_options(struct ast_vm_user *vmu, const char *options)
00694 {
00695 char *stringp;
00696 char *s;
00697 char *var, *value;
00698 stringp = ast_strdupa(options);
00699 while ((s = strsep(&stringp, "|"))) {
00700 value = s;
00701 if ((var = strsep(&value, "=")) && value) {
00702 apply_option(vmu, var, value);
00703 }
00704 }
00705 }
00706
00707 static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *var)
00708 {
00709 struct ast_variable *tmp;
00710 tmp = var;
00711 while (tmp) {
00712 if (!strcasecmp(tmp->name, "vmsecret")) {
00713 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00714 } else if (!strcasecmp(tmp->name, "secret") || !strcasecmp(tmp->name, "password")) {
00715 if (ast_strlen_zero(retval->password))
00716 ast_copy_string(retval->password, tmp->value, sizeof(retval->password));
00717 } else if (!strcasecmp(tmp->name, "uniqueid")) {
00718 ast_copy_string(retval->uniqueid, tmp->value, sizeof(retval->uniqueid));
00719 } else if (!strcasecmp(tmp->name, "pager")) {
00720 ast_copy_string(retval->pager, tmp->value, sizeof(retval->pager));
00721 } else if (!strcasecmp(tmp->name, "email")) {
00722 ast_copy_string(retval->email, tmp->value, sizeof(retval->email));
00723 } else if (!strcasecmp(tmp->name, "fullname")) {
00724 ast_copy_string(retval->fullname, tmp->value, sizeof(retval->fullname));
00725 } else if (!strcasecmp(tmp->name, "context")) {
00726 ast_copy_string(retval->context, tmp->value, sizeof(retval->context));
00727 #ifdef IMAP_STORAGE
00728 } else if (!strcasecmp(tmp->name, "imapuser")) {
00729 ast_copy_string(retval->imapuser, tmp->value, sizeof(retval->imapuser));
00730 } else if (!strcasecmp(tmp->name, "imappassword") || !strcasecmp(tmp->name, "imapsecret")) {
00731 ast_copy_string(retval->imappassword, tmp->value, sizeof(retval->imappassword));
00732 #endif
00733 } else
00734 apply_option(retval, tmp->name, tmp->value);
00735 tmp = tmp->next;
00736 }
00737 }
00738
00739 static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00740 {
00741 struct ast_variable *var;
00742 struct ast_vm_user *retval;
00743
00744 if ((retval = (ivm ? ivm : ast_calloc(1, sizeof(*retval))))) {
00745 if (!ivm)
00746 ast_set_flag(retval, VM_ALLOCED);
00747 else
00748 memset(retval, 0, sizeof(*retval));
00749 if (mailbox)
00750 ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox));
00751 populate_defaults(retval);
00752 if (!context && ast_test_flag((&globalflags), VM_SEARCH))
00753 var = ast_load_realtime("voicemail", "mailbox", mailbox, NULL);
00754 else
00755 var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, NULL);
00756 if (var) {
00757 apply_options_full(retval, var);
00758 ast_variables_destroy(var);
00759 } else {
00760 if (!ivm)
00761 free(retval);
00762 retval = NULL;
00763 }
00764 }
00765 return retval;
00766 }
00767
00768 static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *context, const char *mailbox)
00769 {
00770
00771 struct ast_vm_user *vmu=NULL, *cur;
00772 AST_LIST_LOCK(&users);
00773
00774 if (!context && !ast_test_flag((&globalflags), VM_SEARCH))
00775 context = "default";
00776
00777 AST_LIST_TRAVERSE(&users, cur, list) {
00778 if (ast_test_flag((&globalflags), VM_SEARCH) && !strcasecmp(mailbox, cur->mailbox))
00779 break;
00780 if (context && (!strcasecmp(context, cur->context)) && (!strcasecmp(mailbox, cur->mailbox)))
00781 break;
00782 }
00783 if (cur) {
00784
00785 if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
00786 memcpy(vmu, cur, sizeof(*vmu));
00787 ast_set2_flag(vmu, !ivm, VM_ALLOCED);
00788 AST_LIST_NEXT(vmu, list) = NULL;
00789 }
00790 } else
00791 vmu = find_user_realtime(ivm, context, mailbox);
00792 AST_LIST_UNLOCK(&users);
00793 return vmu;
00794 }
00795