Allow configuration of minsecs and nextaftercmd per mailbox.

Previously only configurable globally. A unit test has also been written to 
provide protection against parse failures for supported mailbox options.

(closes issue )
Reported by: kobaz
Patches: 
      voicemail2.patch uploaded by kobaz (license 834)

Review: https://reviewboard.asterisk.org/r/555/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@254321 65c4cc65-6c06-0410-ace0-fbb531ad65f3
certified/1.8.6
Jeff Peeler 15 years ago
parent 5990fe07b8
commit 560d5c6099

@ -121,6 +121,7 @@ Applications
* Voicemail now supports per mailbox settings for folders when using IMAP storage. * Voicemail now supports per mailbox settings for folders when using IMAP storage.
Previously the folder could only be set per context, but has now been extended Previously the folder could only be set per context, but has now been extended
using the imapfolder option. using the imapfolder option.
* Voicemail now supports per mailbox settings for nextaftercmd and minsecs.
* Voicemail now allows the pager date format to be specified separately from the * Voicemail now allows the pager date format to be specified separately from the
email date format. email date format.
* New applications JabberJoin, JabberLeave, and JabberSendGroup have been added * New applications JabberJoin, JabberLeave, and JabberSendGroup have been added

@ -624,6 +624,7 @@ struct ast_vm_user {
char attachfmt[20]; /*!< Attachment format */ char attachfmt[20]; /*!< Attachment format */
unsigned int flags; /*!< VM_ flags */ unsigned int flags; /*!< VM_ flags */
int saydurationm; int saydurationm;
int minsecs; /*!< Minimum number of seconds per message for this mailbox */
int maxmsg; /*!< Maximum number of msgs per folder for this mailbox */ int maxmsg; /*!< Maximum number of msgs per folder for this mailbox */
int maxdeletedmsg; /*!< Maximum number of deleted msgs saved for this mailbox */ int maxdeletedmsg; /*!< Maximum number of deleted msgs saved for this mailbox */
int maxsecs; /*!< Maximum number of seconds per message for this mailbox */ int maxsecs; /*!< Maximum number of seconds per message for this mailbox */
@ -967,18 +968,25 @@ static void populate_defaults(struct ast_vm_user *vmu)
{ {
ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL); ast_copy_flags(vmu, (&globalflags), AST_FLAGS_ALL);
vmu->passwordlocation = passwordlocation; vmu->passwordlocation = passwordlocation;
if (saydurationminfo) if (saydurationminfo) {
vmu->saydurationm = saydurationminfo; vmu->saydurationm = saydurationminfo;
}
ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback)); ast_copy_string(vmu->callback, callcontext, sizeof(vmu->callback));
ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout)); ast_copy_string(vmu->dialout, dialcontext, sizeof(vmu->dialout));
ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit)); ast_copy_string(vmu->exit, exitcontext, sizeof(vmu->exit));
ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag)); ast_copy_string(vmu->zonetag, zonetag, sizeof(vmu->zonetag));
if (vmmaxsecs) if (vmminsecs) {
vmu->minsecs = vmminsecs;
}
if (vmmaxsecs) {
vmu->maxsecs = vmmaxsecs; vmu->maxsecs = vmmaxsecs;
if (maxmsg) }
if (maxmsg) {
vmu->maxmsg = maxmsg; vmu->maxmsg = maxmsg;
if (maxdeletedmsg) }
if (maxdeletedmsg) {
vmu->maxdeletedmsg = maxdeletedmsg; vmu->maxdeletedmsg = maxdeletedmsg;
}
vmu->volgain = volgain; vmu->volgain = volgain;
vmu->emailsubject = NULL; vmu->emailsubject = NULL;
vmu->emailbody = NULL; vmu->emailbody = NULL;
@ -1057,6 +1065,13 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v
ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout)); ast_copy_string(vmu->dialout, value, sizeof(vmu->dialout));
} else if (!strcasecmp(var, "exitcontext")) { } else if (!strcasecmp(var, "exitcontext")) {
ast_copy_string(vmu->exit, value, sizeof(vmu->exit)); ast_copy_string(vmu->exit, value, sizeof(vmu->exit));
} else if (!strcasecmp(var, "minsecs")) {
if (sscanf(value, "%30d", &x) == 1 && x >= 0) {
vmu->minsecs = x;
} else {
ast_log(LOG_WARNING, "Invalid min message length of %s. Using global value %d\n", value, vmminsecs);
vmu->minsecs = vmminsecs;
}
} else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) { } else if (!strcasecmp(var, "maxmessage") || !strcasecmp(var, "maxsecs")) {
vmu->maxsecs = atoi(value); vmu->maxsecs = atoi(value);
if (vmu->maxsecs <= 0) { if (vmu->maxsecs <= 0) {
@ -1077,6 +1092,8 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v
ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value); ast_log(AST_LOG_WARNING, "Maximum number of messages per folder is %d. Cannot accept value maxmsg=%s\n", MAXMSGLIMIT, value);
vmu->maxmsg = MAXMSGLIMIT; vmu->maxmsg = MAXMSGLIMIT;
} }
} else if (!strcasecmp(var, "nextaftercmd")) {
ast_set2_flag(vmu, ast_true(value), VM_SKIPAFTERCMD);
} else if (!strcasecmp(var, "backupdeleted")) { } else if (!strcasecmp(var, "backupdeleted")) {
if (sscanf(value, "%30d", &x) == 1) if (sscanf(value, "%30d", &x) == 1)
vmu->maxdeletedmsg = x; vmu->maxdeletedmsg = x;
@ -5683,10 +5700,9 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
if (txt) { if (txt) {
fprintf(txt, "flag=%s\n", flag); fprintf(txt, "flag=%s\n", flag);
if (duration < vmminsecs) { if (duration < vmu->minsecs) {
fclose(txt); fclose(txt);
if (option_verbose > 2) ast_verb(3, "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmu->minsecs);
ast_verbose( VERBOSE_PREFIX_3 "Recording was %d seconds long but needs to be at least %d - abandoning\n", duration, vmminsecs);
ast_filedelete(tmptxtfile, NULL); ast_filedelete(tmptxtfile, NULL);
unlink(tmptxtfile); unlink(tmptxtfile);
if (ast_check_realtime("voicemail_data")) { if (ast_check_realtime("voicemail_data")) {
@ -5802,7 +5818,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
} else if (res > 0) } else if (res > 0)
res = 0; res = 0;
if (duration < vmminsecs) if (duration < vmu->minsecs)
/* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */ /* XXX We should really give a prompt too short/option start again, with leave_vm_out called only after a timeout XXX */
pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED"); pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED");
else else
@ -9837,7 +9853,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
vms.oldmessages++; vms.oldmessages++;
cmd = ast_play_and_wait(chan, "vm-undeleted"); cmd = ast_play_and_wait(chan, "vm-undeleted");
} }
if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) { if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
if (vms.curmsg < vms.lastmsg) { if (vms.curmsg < vms.lastmsg) {
vms.curmsg++; vms.curmsg++;
cmd = play_message(chan, vmu, &vms); cmd = play_message(chan, vmu, &vms);
@ -10213,6 +10229,171 @@ static int append_mailbox(const char *context, const char *box, const char *data
return 0; return 0;
} }
AST_TEST_DEFINE(test_voicemail_vmuser)
{
int res = 0;
struct ast_vm_user *vmu;
/* language parameter seems to only be used for display in manager action */
static const char options_string[] = "attach=yes|attachfmt=wav49|"
"serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
"sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
"envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
"forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
"exitcontext=somecontext3|minsecs=10|maxsecs=100|nextaftercmd=yes|"
"backupdeleted=50|volgain=1.3|passwordlocation=spooldir";
#ifdef IMAP_STORAGE
static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
"imapfolder=INBOX|imapvmshareid=6000";
#endif
switch (cmd) {
case TEST_INIT:
info->name = "vmuser";
info->category = "apps/app_voicemail/";
info->summary = "Vmuser unit test";
info->description =
"This tests passing all supported parameters to apply_options, the voicemail user config parser";
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
if (!(vmu = ast_calloc(1, sizeof(*vmu)))) {
return AST_TEST_NOT_RUN;
}
ast_set_flag(vmu, VM_ALLOCED);
apply_options(vmu, options_string);
if (!ast_test_flag(vmu, VM_ATTACH)) {
ast_test_status_update(test, "Parse failure for attach option\n");
res = 1;
}
if (strcasecmp(vmu->attachfmt, "wav49")) {
ast_test_status_update(test, "Parse failure for attachftm option\n");
res = 1;
}
if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
ast_test_status_update(test, "Parse failure for serveremail option\n");
res = 1;
}
if (strcasecmp(vmu->zonetag, "central")) {
ast_test_status_update(test, "Parse failure for tz option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_DELETE)) {
ast_test_status_update(test, "Parse failure for delete option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_SAYCID)) {
ast_test_status_update(test, "Parse failure for saycid option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_SVMAIL)) {
ast_test_status_update(test, "Parse failure for sendvoicemail option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_REVIEW)) {
ast_test_status_update(test, "Parse failure for review option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) {
ast_test_status_update(test, "Parse failure for tempgreetwarm option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_MESSAGEWRAP)) {
ast_test_status_update(test, "Parse failure for messagewrap option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_OPERATOR)) {
ast_test_status_update(test, "Parse failure for operator option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_ENVELOPE)) {
ast_test_status_update(test, "Parse failure for envelope option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_MOVEHEARD)) {
ast_test_status_update(test, "Parse failure for moveheard option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_SAYDURATION)) {
ast_test_status_update(test, "Parse failure for sayduration option\n");
res = 1;
}
if (vmu->saydurationm != 5) {
ast_test_status_update(test, "Parse failure for saydurationm option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_FORCENAME)) {
ast_test_status_update(test, "Parse failure for forcename option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_FORCEGREET)) {
ast_test_status_update(test, "Parse failure for forcegreetings option\n");
res = 1;
}
if (strcasecmp(vmu->callback, "somecontext")) {
ast_test_status_update(test, "Parse failure for callbacks option\n");
res = 1;
}
if (strcasecmp(vmu->dialout, "somecontext2")) {
ast_test_status_update(test, "Parse failure for dialout option\n");
res = 1;
}
if (strcasecmp(vmu->exit, "somecontext3")) {
ast_test_status_update(test, "Parse failure for exitcontext option\n");
res = 1;
}
if (vmu->minsecs != 10) {
ast_test_status_update(test, "Parse failure for minsecs option\n");
res = 1;
}
if (vmu->maxsecs != 100) {
ast_test_status_update(test, "Parse failure for maxsecs option\n");
res = 1;
}
if (!ast_test_flag(vmu, VM_SKIPAFTERCMD)) {
ast_test_status_update(test, "Parse failure for nextaftercmd option\n");
res = 1;
}
if (vmu->maxdeletedmsg != 50) {
ast_test_status_update(test, "Parse failure for backupdeleted option\n");
res = 1;
}
if (vmu->volgain != 1.3) {
ast_test_status_update(test, "Parse failure for volgain option\n");
res = 1;
}
if (vmu->passwordlocation != OPT_PWLOC_SPOOLDIR) {
ast_test_status_update(test, "Parse failure for passwordlocation option\n");
res = 1;
}
#ifdef IMAP_STORAGE
apply_options(vmu, option_string2);
if (strcasecmp(vmu->imapuser, "imapuser")) {
ast_test_status_update(test, "Parse failure for imapuser option\n");
res = 1;
}
if (strcasecmp(vmu->imappassword, "imappasswd")) {
ast_test_status_update(test, "Parse failure for imappasswd option\n");
res = 1;
}
if (strcasecmp(vmu->imapfolder, "INBOX")) {
ast_test_status_update(test, "Parse failure for imappasswd option\n");
res = 1;
}
if (strcasecmp(vmu->imapvmshareid, "6000")) {
ast_test_status_update(test, "Parse failure for imapvmshareid option\n");
res = 1;
}
#endif
free_user(vmu);
return res ? AST_TEST_FAIL : AST_TEST_PASS;
}
static int vm_box_exists(struct ast_channel *chan, const char *data) static int vm_box_exists(struct ast_channel *chan, const char *data)
{ {
struct ast_vm_user svm; struct ast_vm_user svm;
@ -11916,6 +12097,7 @@ static int unload_module(void)
#ifdef TEST_FRAMEWORK #ifdef TEST_FRAMEWORK
res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname); res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname);
res |= AST_TEST_UNREGISTER(test_voicemail_msgcount); res |= AST_TEST_UNREGISTER(test_voicemail_msgcount);
res |= AST_TEST_UNREGISTER(test_voicemail_vmuser);
#endif #endif
ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail)); ast_cli_unregister_multiple(cli_voicemail, ARRAY_LEN(cli_voicemail));
ast_uninstall_vm_functions(); ast_uninstall_vm_functions();
@ -11963,6 +12145,7 @@ static int load_module(void)
#ifdef TEST_FRAMEWORK #ifdef TEST_FRAMEWORK
res |= AST_TEST_REGISTER(test_voicemail_vmsayname); res |= AST_TEST_REGISTER(test_voicemail_vmsayname);
res |= AST_TEST_REGISTER(test_voicemail_msgcount); res |= AST_TEST_REGISTER(test_voicemail_msgcount);
res |= AST_TEST_REGISTER(test_voicemail_vmuser);
#endif #endif
if (res) if (res)

@ -270,7 +270,6 @@ sendvoicemail=yes ; Allow the user to compose and send a voicemail while inside
; much gain to add to the message when sending a voicemail. ; much gain to add to the message when sending a voicemail.
; NOTE: sox must be installed for this option to work. ; NOTE: sox must be installed for this option to work.
; nextaftercmd=yes ; Skips to the next message after hitting 7 or 9 to delete/save current message. ; nextaftercmd=yes ; Skips to the next message after hitting 7 or 9 to delete/save current message.
; [global option only at this time]
; forcename=yes ; Forces a new user to record their name. A new user is ; forcename=yes ; Forces a new user to record their name. A new user is
; determined by the password being the same as ; determined by the password being the same as
; the mailbox number. The default is "no". ; the mailbox number. The default is "no".

Loading…
Cancel
Save