Merged revisions 333370 via svnmerge from
authorMatthew Jordan <mjordan@digium.com>
Fri, 26 Aug 2011 16:12:13 +0000 (16:12 +0000)
committerMatthew Jordan <mjordan@digium.com>
Fri, 26 Aug 2011 16:12:13 +0000 (16:12 +0000)
https://origsvn.digium.com/svn/asterisk/branches/10

................
  r333370 | mjordan | 2011-08-26 10:58:37 -0500 (Fri, 26 Aug 2011) | 26 lines

  Merged revisions 333339 via svnmerge from
  https://origsvn.digium.com/svn/asterisk/branches/1.8

  ........
    r333339 | mjordan | 2011-08-26 08:36:36 -0500 (Fri, 26 Aug 2011) | 20 lines

    Bug fixes for voicemail user emailsubject / emailbody.

    This code change fixes a few issues with the voicemail user override of
    emailbody and emailsubject, including escaping the strings, potential memory
    leaks, and not overriding the voicemail defaults.  Revision 325877 fixed this
    for ASTERISK-16795, but did not fix it for ASTERISK-16781.  A subsequent
    check-in prevented 325877 from being applied to 10.  This check-in resolves
    both issues, and applies the changes to 1.8, 10, and trunk.

    (closes issue ASTERISK-16781)
    Reported by: Sebastien Couture
    Tested by: mjordan

    (closes issue ASTERISK-16795)
    Reported by: mdeneen
    Tested by: mjordan

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

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@333371 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_voicemail.c

index 7a3ebfd..236fc0a 100644 (file)
@@ -916,6 +916,7 @@ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format,
 static int is_valid_dtmf(const char *key);
 static void read_password_from_file(const char *secretfn, char *password, int passwordlen);
 static int write_password_to_file(const char *secretfn, const char *password);
+static const char *substitute_escapes(const char *value);
 
 struct ao2_container *inprocess_container;
 
@@ -1008,10 +1009,11 @@ static char *strip_control_and_high(const char *input, char *buf, size_t buflen)
  * - the exitcontext
  * - vmmaxsecs, vmmaxmsg, maxdeletedmsg
  * - volume gain.
+ * - emailsubject, emailbody set to NULL
  */
 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;
        if (saydurationminfo) {
                vmu->saydurationm = saydurationminfo;
@@ -1034,7 +1036,9 @@ static void populate_defaults(struct ast_vm_user *vmu)
                vmu->maxdeletedmsg = maxdeletedmsg;
        }
        vmu->volgain = volgain;
+       ast_free(vmu->emailsubject);
        vmu->emailsubject = NULL;
+       ast_free(vmu->emailbody);
        vmu->emailbody = NULL;
 #ifdef IMAP_STORAGE
        ast_copy_string(vmu->imapfolder, imapfolder, sizeof(vmu->imapfolder));
@@ -1058,6 +1062,12 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v
                ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
        } else if (!strcasecmp(var, "serveremail")) {
                ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
+       } else if (!strcasecmp(var, "emailbody")) {
+               ast_free(vmu->emailbody);
+               vmu->emailbody = ast_strdup(substitute_escapes(value));
+       } else if (!strcasecmp(var, "emailsubject")) {
+               ast_free(vmu->emailsubject);
+               vmu->emailsubject = ast_strdup(substitute_escapes(value));
        } else if (!strcasecmp(var, "language")) {
                ast_copy_string(vmu->language, value, sizeof(vmu->language));
        } else if (!strcasecmp(var, "tz")) {
@@ -1330,9 +1340,11 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable *
                } else if (!strcasecmp(var->name, "context")) {
                        ast_copy_string(retval->context, var->value, sizeof(retval->context));
                } else if (!strcasecmp(var->name, "emailsubject")) {
-                       retval->emailsubject = ast_strdup(var->value);
+                       ast_free(retval->emailsubject);
+                       retval->emailsubject = ast_strdup(substitute_escapes(var->value));
                } else if (!strcasecmp(var->name, "emailbody")) {
-                       retval->emailbody = ast_strdup(var->value);
+                       ast_free(retval->emailbody);
+                       retval->emailbody = ast_strdup(substitute_escapes(var->value));
 #ifdef IMAP_STORAGE
                } else if (!strcasecmp(var->name, "imapuser")) {
                        ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser));
@@ -1443,7 +1455,11 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex
        if (cur) {
                /* Make a copy, so that on a reload, we have no race */
                if ((vmu = (ivm ? ivm : ast_malloc(sizeof(*vmu))))) {
-                       memcpy(vmu, cur, sizeof(*vmu));
+                       *vmu = *cur;
+                       if (!ivm) {
+                               vmu->emailbody = ast_strdup(cur->emailbody);
+                               vmu->emailsubject = ast_strdup(cur->emailsubject);
+                       }
                        ast_set2_flag(vmu, !ivm, VM_ALLOCED);
                        AST_LIST_NEXT(vmu, list) = NULL;
                }
@@ -1722,14 +1738,13 @@ static int get_folder_by_name(const char *name)
 static void free_user(struct ast_vm_user *vmu)
 {
        if (ast_test_flag(vmu, VM_ALLOCED)) {
-               if (vmu->emailbody != NULL) {
-                       ast_free(vmu->emailbody);
-                       vmu->emailbody = NULL;
-               }
-               if (vmu->emailsubject != NULL) {
-                       ast_free(vmu->emailsubject);
-                       vmu->emailsubject = NULL;
-               }
+
+               ast_free(vmu->emailbody);
+               vmu->emailbody = NULL;
+
+               ast_free(vmu->emailsubject);
+               vmu->emailsubject = NULL;
+
                ast_free(vmu);
        }
 }
@@ -10764,7 +10779,9 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
                "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";
+               "backupdeleted=50|volgain=1.3|passwordlocation=spooldir|emailbody="
+               "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message|emailsubject="
+               "[PBX]: New message \\\\${VM_MSGNUM}\\\\ in mailbox ${VM_MAILBOX}";
 #ifdef IMAP_STORAGE
        static const char option_string2[] = "imapuser=imapuser|imappassword=imappasswd|"
                "imapfolder=INBOX|imapvmshareid=6000";
@@ -10786,6 +10803,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
                return AST_TEST_NOT_RUN;
        }
        ast_set_flag(vmu, VM_ALLOCED);
+       populate_defaults(vmu);
 
        apply_options(vmu, options_string);
 
@@ -10801,6 +10819,14 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
                ast_test_status_update(test, "Parse failure for serveremail option\n");
                res = 1;
        }
+       if (!vmu->emailsubject || strcasecmp(vmu->emailsubject, "[PBX]: New message \\${VM_MSGNUM}\\ in mailbox ${VM_MAILBOX}")) {
+               ast_test_status_update(test, "Parse failure for emailsubject option\n");
+               res = 1;
+       }
+       if (!vmu->emailbody || strcasecmp(vmu->emailbody, "Dear ${VM_NAME}:\n\n\tYou were just left a ${VM_DUR} long message")) {
+               ast_test_status_update(test, "Parse failure for emailbody option\n");
+               res = 1;
+       }
        if (strcasecmp(vmu->zonetag, "central")) {
                ast_test_status_update(test, "Parse failure for tz option\n");
                res = 1;
@@ -11700,6 +11726,9 @@ static const char *substitute_escapes(const char *value)
                                break;
                        }
                        switch (*current) {
+                       case '\\':
+                               ast_str_append(&str, 0, "\\");
+                               break;
                        case 'r':
                                ast_str_append(&str, 0, "\r");
                                break;
@@ -12391,13 +12420,13 @@ static int load_config(int reload)
                        ast_copy_string(locale, val, sizeof(locale));
                }
                if ((val = ast_variable_retrieve(cfg, "general", "emailsubject"))) {
-                       emailsubject = ast_strdup(val);
+                       emailsubject = ast_strdup(substitute_escapes(val));
                }
                if ((val = ast_variable_retrieve(cfg, "general", "emailbody"))) {
                        emailbody = ast_strdup(substitute_escapes(val));
                }
                if ((val = ast_variable_retrieve(cfg, "general", "pagersubject"))) {
-                       pagersubject = ast_strdup(val);
+                       pagersubject = ast_strdup(substitute_escapes(val));
                }
                if ((val = ast_variable_retrieve(cfg, "general", "pagerbody"))) {
                        pagerbody = ast_strdup(substitute_escapes(val));