<p>Joshua C. Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10800">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Sean Bright: Looks good to me, but someone else must approve
Joshua C. Colp: Looks good to me, approved; Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">app_voicemail: Add Mailbox Aliases<br><br>You can now define an "aliases" context in voicemail.conf<br>whose entries point to actual mailboxes. These can be used anywhere<br>the mailbox is specified.<br><br>Example:<br>[general]<br>aliasescontext = myaliases<br><br>[default]<br>1234 = yadayada<br><br>[myaliases]<br>4321@devices = 1234@default<br><br>Now you can use 4321@devices to refer to the 1234@default mailbox.<br><br>This can be useful to provide channel drivers with constant<br>mailbox specifications such as <extension>@devices leaving<br>app_voicemail to control exactly which mailbox the alias points to.<br>Now, only voicemail has to be reloaded to make changes instead of<br>individual channel drivers which are usually more expensive to<br>reload.<br><br>Change-Id: I395b9205c91523a334fe971be0d1de4522067b04<br>---<br>M CHANGES<br>M apps/app_voicemail.c<br>M configs/samples/voicemail.conf.sample<br>3 files changed, 288 insertions(+), 45 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/CHANGES b/CHANGES</span><br><span>index e099ce0..48fed93 100644</span><br><span>--- a/CHANGES</span><br><span>+++ b/CHANGES</span><br><span>@@ -30,6 +30,12 @@</span><br><span> The previous behavior has been restored so both channels receive the</span><br><span> channel variable when one of these features is invoked.</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+app_voicemail</span><br><span style="color: hsl(120, 100%, 40%);">+------------------</span><br><span style="color: hsl(120, 100%, 40%);">+ * You can now specify a special context with the "aliasescontext" parameter</span><br><span style="color: hsl(120, 100%, 40%);">+ in voicemail.conf which will allow you to create aliases for physical</span><br><span style="color: hsl(120, 100%, 40%);">+ mailboxes.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> ------------------------------------------------------------------------------</span><br><span> --- Functionality changes from Asterisk 16.0.0 to Asterisk 16.1.0 ------------</span><br><span> ------------------------------------------------------------------------------</span><br><span>diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c</span><br><span>index d132e2b..3223af6 100644</span><br><span>--- a/apps/app_voicemail.c</span><br><span>+++ b/apps/app_voicemail.c</span><br><span>@@ -999,6 +999,7 @@</span><br><span> static int maxlogins;</span><br><span> static int minpassword;</span><br><span> static int passwordlocation;</span><br><span style="color: hsl(120, 100%, 40%);">+static char aliasescontext[MAX_VM_CONTEXT_LEN];</span><br><span> </span><br><span> /*! Poll mailboxes for changes since there is something external to</span><br><span> * app_voicemail that may change them. */</span><br><span>@@ -1051,6 +1052,27 @@</span><br><span> </span><br><span> static AST_RWLIST_HEAD_STATIC(mwi_subs, mwi_sub);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct alias_mailbox_mapping {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *alias;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *mailbox;</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[0];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct mailbox_alias_mapping {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *alias;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *mailbox;</span><br><span style="color: hsl(120, 100%, 40%);">+ char buf[0];</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAPPING_BUCKETS 511</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ao2_container *alias_mailbox_mappings;</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_HASH_FN(alias_mailbox_mapping, alias);</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_CMP_FN(alias_mailbox_mapping, alias);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ao2_container *mailbox_alias_mappings;</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_HASH_FN(mailbox_alias_mapping, mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+AO2_STRING_FIELD_CMP_FN(mailbox_alias_mapping, mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* custom audio control prompts for voicemail playback */</span><br><span> static char listen_control_forward_key[12];</span><br><span> static char listen_control_reverse_key[12];</span><br><span>@@ -1765,9 +1787,31 @@</span><br><span> ast_set2_flag(vmu, !ivm, VM_ALLOCED);</span><br><span> AST_LIST_NEXT(vmu, list) = NULL;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- } else</span><br><span style="color: hsl(0, 100%, 40%);">- vmu = find_user_realtime(ivm, context, mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> AST_LIST_UNLOCK(&users);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vmu) {</span><br><span style="color: hsl(120, 100%, 40%);">+ vmu = find_user_realtime(ivm, context, mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vmu && !ast_strlen_zero(aliasescontext)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *search_string = ast_alloca(MAX_VM_MAILBOX_LEN);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(search_string, MAX_VM_MAILBOX_LEN, "%s%s%s",</span><br><span style="color: hsl(120, 100%, 40%);">+ mailbox,</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_strlen_zero(context) ? "" : "@",</span><br><span style="color: hsl(120, 100%, 40%);">+ S_OR(context, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mapping = ao2_find(alias_mailbox_mappings, search_string, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mapping) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *search_mailbox = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *search_context = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ separate_mailbox(ast_strdupa(mapping->mailbox), &search_mailbox, &search_context);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(mapping, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ vmu = find_user(ivm, search_mailbox, search_context);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return vmu;</span><br><span> }</span><br><span> </span><br><span>@@ -6056,6 +6100,9 @@</span><br><span> struct dirent *de;</span><br><span> char fn[256];</span><br><span> int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *c;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *m;</span><br><span> </span><br><span> /* If no mailbox, return immediately */</span><br><span> if (ast_strlen_zero(mailbox))</span><br><span>@@ -6066,7 +6113,21 @@</span><br><span> if (ast_strlen_zero(context))</span><br><span> context = "default";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, context, mailbox, folder);</span><br><span style="color: hsl(120, 100%, 40%);">+ c = (char *)context;</span><br><span style="color: hsl(120, 100%, 40%);">+ m = (char *)mailbox;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(aliasescontext)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char tmp[MAX_VM_MAILBOX_LEN];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(tmp, MAX_VM_MAILBOX_LEN, "%s@%s", mailbox, context);</span><br><span style="color: hsl(120, 100%, 40%);">+ mapping = ao2_find(alias_mailbox_mappings, tmp, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mapping) {</span><br><span style="color: hsl(120, 100%, 40%);">+ separate_mailbox(ast_strdupa(mapping->mailbox), &m, &c);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(mapping, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(fn, sizeof(fn), "%s%s/%s/%s", VM_SPOOL_DIR, c, m, folder);</span><br><span> </span><br><span> if (!(dir = opendir(fn)))</span><br><span> return 0;</span><br><span>@@ -8096,7 +8157,24 @@</span><br><span> return;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Queueing event for mailbox %s New: %d Old: %d\n", box, new + urgent, old);</span><br><span> ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_strlen_zero(aliasescontext)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_iterator *aliases;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mailbox_alias_mapping *mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ aliases = ao2_find(mailbox_alias_mappings, box, OBJ_SEARCH_KEY | OBJ_MULTIPLE);</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((mapping = ao2_iterator_next(aliases))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mailbox = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ context = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);</span><br><span style="color: hsl(120, 100%, 40%);">+ separate_mailbox(ast_strdupa(mapping->alias), &mailbox, &context);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(mapping, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_iterator_destroy(aliases);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -13000,6 +13078,46 @@</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Show a list of voicemail zones in the CLI */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *handle_voicemail_show_aliases(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ao2_iterator aliases;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+#define ALIASES_OUTPUT_FORMAT "%-32s %-32s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ char *res = CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "voicemail show aliases";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: voicemail show aliases\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Lists mailbox aliases\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc != 3)</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(aliasescontext)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Aliases are not enabled\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Aliases context: %s\n", aliasescontext);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, "Alias", "Mailbox");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ aliases = ao2_iterator_init(alias_mailbox_mappings, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((mapping = ao2_iterator_next(&aliases))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, ALIASES_OUTPUT_FORMAT, mapping->alias, mapping->mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(mapping, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_iterator_destroy(&aliases);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Reload voicemail configuration from the CLI */</span><br><span> static char *handle_voicemail_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span> {</span><br><span>@@ -13026,6 +13144,7 @@</span><br><span> static struct ast_cli_entry cli_voicemail[] = {</span><br><span> AST_CLI_DEFINE(handle_voicemail_show_users, "List defined voicemail boxes"),</span><br><span> AST_CLI_DEFINE(handle_voicemail_show_zones, "List zone message formats"),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(handle_voicemail_show_aliases, "List mailbox aliases"),</span><br><span> AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"),</span><br><span> };</span><br><span> </span><br><span>@@ -13244,7 +13363,6 @@</span><br><span> if (stasis_message_type(msg) != stasis_subscription_change_type()) {</span><br><span> return;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> change = stasis_message_data(msg);</span><br><span> if (change->topic == ast_mwi_topic_all()) {</span><br><span> return;</span><br><span>@@ -13662,11 +13780,98 @@</span><br><span> }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static struct alias_mailbox_mapping *alias_mailbox_mapping_create(const char *alias, const char *mailbox)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t from_len = strlen(alias) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t to_len = strlen(mailbox) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mapping = ao2_alloc(sizeof(*mapping) + from_len + to_len, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mapping) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ mapping->alias = mapping->buf;</span><br><span style="color: hsl(120, 100%, 40%);">+ mapping->mailbox = mapping->buf + from_len;</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy(mapping->alias, alias); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+ strcpy(mapping->mailbox, mailbox); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return mapping;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void load_aliases(struct ast_config *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(aliasescontext)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ var = ast_variable_browse(cfg, aliasescontext);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (var) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping = alias_mailbox_mapping_create(var->name, var->value);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mapping) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_link(alias_mailbox_mappings, mapping);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_link(mailbox_alias_mappings, mapping);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_ref(mapping, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ var = var->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void load_zonemessages(struct ast_config *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ var = ast_variable_browse(cfg, "zonemessages");</span><br><span style="color: hsl(120, 100%, 40%);">+ while (var) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct vm_zone *z;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *msg_format, *tzone;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ z = ast_malloc(sizeof(*z));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!z) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ msg_format = ast_strdupa(var->value);</span><br><span style="color: hsl(120, 100%, 40%);">+ tzone = strsep(&msg_format, "|,");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (msg_format) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(z->name, var->name, sizeof(z->name));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(z->timezone, tzone, sizeof(z->timezone));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_LOCK(&zones);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_INSERT_HEAD(&zones, z, list);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_UNLOCK(&zones);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(z);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ var = var->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void load_users(struct ast_config *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_variable *var;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *cat = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((cat = ast_category_browse(cfg, cat))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcasecmp(cat, "general") == 0</span><br><span style="color: hsl(120, 100%, 40%);">+ || strcasecmp(cat, aliasescontext) == 0</span><br><span style="color: hsl(120, 100%, 40%);">+ || strcasecmp(cat, "zonemessages") == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ var = ast_variable_browse(cfg, cat);</span><br><span style="color: hsl(120, 100%, 40%);">+ while (var) {</span><br><span style="color: hsl(120, 100%, 40%);">+ append_mailbox(cat, var->name, var->value);</span><br><span style="color: hsl(120, 100%, 40%);">+ var = var->next;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int actual_load_config(int reload, struct ast_config *cfg, struct ast_config *ucfg)</span><br><span> {</span><br><span> struct ast_vm_user *current;</span><br><span> char *cat;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_variable *var;</span><br><span> const char *val;</span><br><span> char *q, *stringp, *tmp;</span><br><span> int x;</span><br><span>@@ -13695,6 +13900,10 @@</span><br><span> /* Free all the zones structure */</span><br><span> free_vm_zones();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Remove all aliases */</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_callback(alias_mailbox_mappings, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_callback(mailbox_alias_mappings, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> AST_LIST_LOCK(&users);</span><br><span> </span><br><span> memset(ext_pass_cmd, 0, sizeof(ext_pass_cmd));</span><br><span>@@ -13706,6 +13915,11 @@</span><br><span> if (!(val = ast_variable_retrieve(cfg, "general", "userscontext")))</span><br><span> val = "default";</span><br><span> ast_copy_string(userscontext, val, sizeof(userscontext));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ aliasescontext[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+ val = ast_variable_retrieve(cfg, "general", "aliasescontext");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(aliasescontext, S_OR(val, ""), sizeof(aliasescontext));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Attach voice message to mail message ? */</span><br><span> if (!(val = ast_variable_retrieve(cfg, "general", "attach")))</span><br><span> val = "yes";</span><br><span>@@ -14307,45 +14521,16 @@</span><br><span> }</span><br><span> </span><br><span> /* load mailboxes from voicemail.conf */</span><br><span style="color: hsl(0, 100%, 40%);">- cat = ast_category_browse(cfg, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- while (cat) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcasecmp(cat, "general")) {</span><br><span style="color: hsl(0, 100%, 40%);">- var = ast_variable_browse(cfg, cat);</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcasecmp(cat, "zonemessages")) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Process mailboxes in this context */</span><br><span style="color: hsl(0, 100%, 40%);">- while (var) {</span><br><span style="color: hsl(0, 100%, 40%);">- append_mailbox(cat, var->name, var->value);</span><br><span style="color: hsl(0, 100%, 40%);">- var = var->next;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Timezones in this context */</span><br><span style="color: hsl(0, 100%, 40%);">- while (var) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct vm_zone *z;</span><br><span style="color: hsl(0, 100%, 40%);">- if ((z = ast_malloc(sizeof(*z)))) {</span><br><span style="color: hsl(0, 100%, 40%);">- char *msg_format, *tzone;</span><br><span style="color: hsl(0, 100%, 40%);">- msg_format = ast_strdupa(var->value);</span><br><span style="color: hsl(0, 100%, 40%);">- tzone = strsep(&msg_format, "|,");</span><br><span style="color: hsl(0, 100%, 40%);">- if (msg_format) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(z->name, var->name, sizeof(z->name));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(z->timezone, tzone, sizeof(z->timezone));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_LOCK(&zones);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_INSERT_HEAD(&zones, z, list);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_UNLOCK(&zones);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(z);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_LIST_UNLOCK(&users);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- var = var->next;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- cat = ast_category_browse(cfg, cat);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Aliases must be loaded before users or the aliases won't be notified</span><br><span style="color: hsl(120, 100%, 40%);">+ * if there's existing voicemail in the user mailbox.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ load_aliases(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ load_zonemessages(cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ load_users(cfg);</span><br><span> </span><br><span> AST_LIST_UNLOCK(&users);</span><br><span> </span><br><span>@@ -15096,6 +15281,16 @@</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void print_mappings(void *v_obj, void *where, ao2_prnt_fn *prnt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct alias_mailbox_mapping *mapping = v_obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mapping) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ prnt(where, "Alias: %s Mailbox: %s", mapping->alias, mapping->mailbox);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*!</span><br><span> * \brief Load the module</span><br><span> *</span><br><span>@@ -15122,6 +15317,38 @@</span><br><span> return AST_MODULE_LOAD_DECLINE;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ alias_mailbox_mappings = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAPPING_BUCKETS,</span><br><span style="color: hsl(120, 100%, 40%);">+ alias_mailbox_mapping_hash_fn, NULL, alias_mailbox_mapping_cmp_fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!alias_mailbox_mappings) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to create alias_mailbox_mappings container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(inprocess_container);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ao2_container_register("voicemail_alias_mailbox_mappings", alias_mailbox_mappings, print_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to register alias_mailbox_mappings container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(inprocess_container);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(alias_mailbox_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mailbox_alias_mappings = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MAPPING_BUCKETS,</span><br><span style="color: hsl(120, 100%, 40%);">+ mailbox_alias_mapping_hash_fn, NULL, mailbox_alias_mapping_cmp_fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!mailbox_alias_mappings) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(inprocess_container);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(alias_mailbox_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ao2_container_register("voicemail_mailbox_alias_mappings", mailbox_alias_mappings, print_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (res) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(inprocess_container);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(alias_mailbox_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(mailbox_alias_mappings);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_MODULE_LOAD_DECLINE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* compute the location of the voicemail spool directory */</span><br><span> snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);</span><br><span> </span><br><span>diff --git a/configs/samples/voicemail.conf.sample b/configs/samples/voicemail.conf.sample</span><br><span>index e4130d3..30054b5 100644</span><br><span>--- a/configs/samples/voicemail.conf.sample</span><br><span>+++ b/configs/samples/voicemail.conf.sample</span><br><span>@@ -73,6 +73,10 @@</span><br><span> ;</span><br><span> ;userscontext=default</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; Aliases allow a mailbox to be referenced by an alias. The aliases are</span><br><span style="color: hsl(120, 100%, 40%);">+; specified in the special context named here. There is no default.</span><br><span style="color: hsl(120, 100%, 40%);">+;aliasescontext=myaliases</span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span> ; If you need to have an external program, i.e. /usr/bin/myapp</span><br><span> ; called when a voicemail is left, delivered, or your voicemailbox</span><br><span> ; is checked, uncomment this.</span><br><span>@@ -233,7 +237,6 @@</span><br><span> ; Default: no</span><br><span> </span><br><span> ; -----------------------------------------------------------------------------</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span> </span><br><span> ; Each mailbox is listed in the form <mailbox>=<password>,<name>,<email>,<pager_email>,<options></span><br><span> ; If email is specified, a message will be sent when a voicemail is received, to</span><br><span>@@ -451,6 +454,13 @@</span><br><span> ;4110 => 3443,Rob Flynn,rflynn@blueridge.net</span><br><span> ;4235 => 1234,Jim Holmes,jim@astricon.ips,,Tz=european</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span style="color: hsl(120, 100%, 40%);">+; Aliases allow alternate references to mailboxes. See the "aliasescontext"</span><br><span style="color: hsl(120, 100%, 40%);">+; parameter in the "general" section.</span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span style="color: hsl(120, 100%, 40%);">+[myaliases]</span><br><span style="color: hsl(120, 100%, 40%);">+1234@devices => 1234@default</span><br><span style="color: hsl(120, 100%, 40%);">+;6200@devices => 4200@default</span><br><span> </span><br><span> ;</span><br><span> ; Mailboxes may be organized into multiple contexts for</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10800">change 10800</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10800"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I395b9205c91523a334fe971be0d1de4522067b04 </div>
<div style="display:none"> Gerrit-Change-Number: 10800 </div>
<div style="display:none"> Gerrit-PatchSet: 8 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation (1000185) </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua C. Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>