static char *complete_mailbox(const char *word, int state) { struct ao2_iterator iter; int wordlen = strlen(word); int which = 0; char *ret = NULL; char *regex; const struct ast_mwi_mailbox_object *mailbox; RAII_VAR(struct ao2_container *, mailboxes, NULL, ao2_cleanup); regex = ast_alloca(2 + wordlen); sprintf(regex, "^%s", word);/* Safe */ mailboxes = ast_mwi_mailbox_get_by_regex(regex); if (!mailboxes) { return NULL; } iter = ao2_iterator_init(mailboxes, 0); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { if (++which > state) { ret = ast_strdup(ast_sorcery_object_get_id(mailbox)); ast_mwi_mailbox_unref(mailbox); break; } } ao2_iterator_destroy(&iter); return ret; }
struct ast_json *stasis_app_mailboxes_to_json() { struct ast_json *array = ast_json_array_create(); struct ao2_container *mailboxes; struct ao2_iterator iter; const struct ast_mwi_mailbox_object *mailbox; if (!array) { return NULL; } mailboxes = ast_mwi_mailbox_get_all(); if (!mailboxes) { ast_json_unref(array); return NULL; } iter = ao2_iterator_init(mailboxes, 0); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { struct ast_json *appending = mailbox_to_json(mailbox); if (!appending || ast_json_array_append(array, appending)) { /* Failed to append individual mailbox to the array. Abort. */ ast_json_unref(array); array = NULL; break; } } ao2_iterator_destroy(&iter); return array; }
/*! * \internal * \brief Gets the number of messages that exist for the mailbox list. * \since 12.1.0 * * \param mailboxes Comma or space delimited list of mailboxes. * \param newmsgs Where to put the count of new messages. (Can be NULL) * \param oldmsgs Where to put the count of old messages. (Can be NULL) * * \details * Simultaneously determines the count of new and old * messages. The total messages would then be the sum of these. * * \retval 0 on success * \retval -1 on failure */ static int mwi_inboxcount(const char *mailboxes, int *newmsgs, int *oldmsgs) { char *parse; char *mailbox_id; if (!newmsgs && !oldmsgs) { /* Nowhere to accumulate counts */ return 0; } /* For each mailbox in the list. */ parse = ast_strdupa(mailboxes); while ((mailbox_id = strsep(&parse, ", "))) { const struct ast_mwi_mailbox_object *mailbox; /* Get the specified mailbox. */ mailbox = ast_mwi_mailbox_get(mailbox_id); if (!mailbox) { continue; } /* Accumulate the counts. */ if (newmsgs) { *newmsgs += mailbox->msgs_new; } if (oldmsgs) { *oldmsgs += mailbox->msgs_old; } ast_mwi_mailbox_unref(mailbox); } return 0; }
/*! * \internal * \brief Gets the number of messages that exist in a mailbox folder. * \since 12.1.0 * * \param mailbox_id The mailbox name. * \param folder The folder to look in. Default is INBOX if not provided. * * \return The number of messages in the mailbox folder (zero or more). */ static int mwi_messagecount(const char *mailbox_id, const char *folder) { const struct ast_mwi_mailbox_object *mailbox; int num_msgs; enum folder_map which_folder; which_folder = mwi_folder_map(folder); if (which_folder == FOLDER_INVALID) { return 0; } mailbox = ast_mwi_mailbox_get(mailbox_id); if (!mailbox) { return 0; } num_msgs = 0; switch (which_folder) { case FOLDER_INVALID: break; case FOLDER_INBOX: num_msgs = mailbox->msgs_new; break; case FOLDER_OLD: num_msgs = mailbox->msgs_old; break; } ast_mwi_mailbox_unref(mailbox); return num_msgs; }
/*! * \internal * \brief Delete all mailboxes in container. * \since 12.1.0 * * \param mailboxes Mailbox objects to delete from sorcery. * * \return Nothing */ static void mwi_mailbox_delete_all(struct ao2_container *mailboxes) { struct ast_mwi_mailbox_object *mailbox; struct ao2_iterator iter; iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { mwi_mailbox_delete(mailbox); } ao2_iterator_destroy(&iter); }
/*! * \internal * \brief List all mailboxes in the given container. * \since 12.1.0 * * \param cli_fd File descriptor for CLI output. * \param mailboxes What to list. * * \return Nothing */ static void mwi_cli_list_mailboxes(int cli_fd, struct ao2_container *mailboxes) { struct ao2_iterator iter; const struct ast_mwi_mailbox_object *mailbox; ast_cli(cli_fd, FORMAT_MAILBOX_HDR, "New", "Old", "Mailbox"); iter = ao2_iterator_init(mailboxes, 0); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { mwi_cli_print_mailbox(cli_fd, mailbox); } ao2_iterator_destroy(&iter); }
int ast_mwi_mailbox_delete(const char *mailbox_id) { const struct ast_mwi_mailbox_object *mailbox; if (ast_strlen_zero(mailbox_id)) { return -1; } mailbox = ast_mwi_mailbox_get(mailbox_id); if (mailbox) { mwi_mailbox_delete((struct ast_mwi_mailbox_object *) mailbox); ast_mwi_mailbox_unref(mailbox); } return 0; }
int ast_mwi_mailbox_update(struct ast_mwi_mailbox_object *mailbox) { const struct ast_mwi_mailbox_object *exists; int res; exists = ast_sorcery_retrieve_by_id(mwi_sorcery, MWI_MAILBOX_TYPE, ast_sorcery_object_get_id(mailbox)); if (exists) { res = ast_sorcery_update(mwi_sorcery, mailbox); ast_mwi_mailbox_unref(exists); } else { res = ast_sorcery_create(mwi_sorcery, mailbox); } return res; }
/*! * \internal * \brief Update the specified mailbox. * \since 12.1.0 * * \param s AMI session. * \param m AMI message. * * \retval 0 to keep AMI connection. * \retval -1 to disconnect AMI connection. */ static int mwi_mailbox_update(struct mansession *s, const struct message *m) { const char *mailbox_id = astman_get_header(m, "Mailbox"); const char *msgs_old = astman_get_header(m, "OldMessages"); const char *msgs_new = astman_get_header(m, "NewMessages"); struct ast_mwi_mailbox_object *mailbox; unsigned int num_old; unsigned int num_new; if (ast_strlen_zero(mailbox_id)) { astman_send_error(s, m, "Missing mailbox parameter in request"); return 0; } num_old = 0; if (!ast_strlen_zero(msgs_old)) { if (sscanf(msgs_old, "%u", &num_old) != 1) { astman_send_error_va(s, m, "Invalid OldMessages: %s", msgs_old); return 0; } } num_new = 0; if (!ast_strlen_zero(msgs_new)) { if (sscanf(msgs_new, "%u", &num_new) != 1) { astman_send_error_va(s, m, "Invalid NewMessages: %s", msgs_new); return 0; } } mailbox = ast_mwi_mailbox_alloc(mailbox_id); if (!mailbox) { astman_send_error(s, m, "Mailbox object creation failure"); return 0; } /* Update external mailbox. */ ast_mwi_mailbox_set_msgs_old(mailbox, num_old); ast_mwi_mailbox_set_msgs_new(mailbox, num_new); if (ast_mwi_mailbox_update(mailbox)) { astman_send_error(s, m, "Update attempt failed"); } else { astman_send_ack(s, m, NULL); } ast_mwi_mailbox_unref(mailbox); return 0; }
/*! * \internal * \brief Determines if the given folder has messages. * \since 12.1.0 * * \param mailboxes Comma or & delimited list of mailboxes. * \param folder The folder to look in. Default is INBOX if not provided. * * \retval 1 if the folder has one or more messages. * \retval 0 otherwise. */ static int mwi_has_voicemail(const char *mailboxes, const char *folder) { char *parse; char *mailbox_id; enum folder_map which_folder; which_folder = mwi_folder_map(folder); if (which_folder == FOLDER_INVALID) { return 0; } /* For each mailbox in the list. */ parse = ast_strdupa(mailboxes); while ((mailbox_id = strsep(&parse, ",&"))) { const struct ast_mwi_mailbox_object *mailbox; int num_msgs; /* Get the specified mailbox. */ mailbox = ast_mwi_mailbox_get(mailbox_id); if (!mailbox) { continue; } /* Done if the found mailbox has any messages. */ num_msgs = 0; switch (which_folder) { case FOLDER_INVALID: break; case FOLDER_INBOX: num_msgs = mailbox->msgs_new; break; case FOLDER_OLD: num_msgs = mailbox->msgs_old; break; } ast_mwi_mailbox_unref(mailbox); if (num_msgs) { return 1; } } return 0; }
int stasis_app_mailbox_update( const char *name, int old_messages, int new_messages) { struct ast_mwi_mailbox_object *mailbox; int res = 0; mailbox = ast_mwi_mailbox_alloc(name); if (!mailbox) { return -1; } ast_mwi_mailbox_set_msgs_new(mailbox, new_messages); ast_mwi_mailbox_set_msgs_old(mailbox, old_messages); if (ast_mwi_mailbox_update(mailbox)) { res = -1; } ast_mwi_mailbox_unref(mailbox); return res; }
static char *handle_mwi_show_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { const struct ast_mwi_mailbox_object *mailbox; const char *mailbox_id; switch (cmd) { case CLI_INIT: e->command = "mwi show mailbox"; e->usage = "Usage: mwi show mailbox <mailbox_id>\n" " Show a specific external MWI mailbox.\n"; return NULL; case CLI_GENERATE: if (a->pos == 3) { return complete_mailbox(a->word, a->n); } return NULL; } if (a->argc != 4) { return CLI_SHOWUSAGE; } mailbox_id = a->argv[3]; mailbox = ast_mwi_mailbox_get(mailbox_id); if (mailbox) { ast_cli(a->fd, "Mailbox: %s\n" "NewMessages: %u\n" "OldMessages: %u\n", ast_sorcery_object_get_id(mailbox), mailbox->msgs_new, mailbox->msgs_old); ast_mwi_mailbox_unref(mailbox); } else { ast_cli(a->fd, "External MWI mailbox '%s' not found.\n", mailbox_id); } return CLI_SUCCESS; }
enum stasis_mailbox_result stasis_app_mailbox_to_json( const char *name, struct ast_json **json) { struct ast_json *mailbox_json; const struct ast_mwi_mailbox_object *mailbox; mailbox = ast_mwi_mailbox_get(name); if (!mailbox) { return STASIS_MAILBOX_MISSING; } mailbox_json = mailbox_to_json(mailbox); if (!mailbox_json) { ast_mwi_mailbox_unref(mailbox); return STASIS_MAILBOX_ERROR; } *json = mailbox_json; return STASIS_MAILBOX_OK; }
enum stasis_mailbox_result stasis_app_mailbox_delete( const char *name) { const struct ast_mwi_mailbox_object *mailbox; /* Make sure the mailbox actually exists before we delete it */ mailbox = ast_mwi_mailbox_get(name); if (!mailbox) { return STASIS_MAILBOX_MISSING; } ast_mwi_mailbox_unref(mailbox); mailbox = NULL; /* Now delete the mailbox */ if (ast_mwi_mailbox_delete(name)) { return STASIS_MAILBOX_ERROR; } return STASIS_MAILBOX_OK; }
/*! * \internal * \brief Post initial MWI count events. * \since 12.1.0 * * \return Nothing */ static void mwi_initial_events(void) { struct ao2_container *mailboxes; const struct ast_mwi_mailbox_object *mailbox; struct ao2_iterator iter; /* Get all mailbox counts. */ mailboxes = ast_mwi_mailbox_get_all(); if (!mailboxes) { return; } /* Post all mailbox counts. */ iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { mwi_post_event(mailbox); } ao2_iterator_destroy(&iter); ao2_ref(mailboxes, -1); }
/*! * \internal * \brief Get the requested mailboxes. * \since 12.1.0 * * \param s AMI session. * \param m AMI message. * * \retval 0 to keep AMI connection. * \retval -1 to disconnect AMI connection. */ static int mwi_mailbox_get(struct mansession *s, const struct message *m) { char id_text[256]; const char *id; const char *mailbox_id = astman_get_header(m, "Mailbox"); const struct ast_mwi_mailbox_object *mailbox; struct ao2_container *mailboxes; unsigned count; struct ao2_iterator iter; if (ast_strlen_zero(mailbox_id)) { astman_send_error(s, m, "Missing mailbox parameter in request"); return 0; } if (*mailbox_id == '/') { struct ast_str *regex_string; regex_string = ast_str_create(strlen(mailbox_id) + 1); if (!regex_string) { astman_send_error(s, m, "Memory Allocation Failure"); return 0; } /* Make "/regex/" into "regex" */ if (ast_regex_string_to_regex_pattern(mailbox_id, ®ex_string) != 0) { astman_send_error_va(s, m, "Mailbox regex format invalid in: %s", mailbox_id); ast_free(regex_string); return 0; } mailboxes = ast_mwi_mailbox_get_by_regex(ast_str_buffer(regex_string)); ast_free(regex_string); } else { mailboxes = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL); if (mailboxes) { mailbox = ast_mwi_mailbox_get(mailbox_id); if (mailbox) { if (!ao2_link(mailboxes, (void *) mailbox)) { ao2_ref(mailboxes, -1); mailboxes = NULL; } ast_mwi_mailbox_unref(mailbox); } } } if (!mailboxes) { astman_send_error(s, m, "Mailbox container creation failure"); return 0; } astman_send_listack(s, m, "Mailboxes will follow", "start"); id = astman_get_header(m, "ActionID"); if (!ast_strlen_zero(id)) { snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id); } else { id_text[0] = '\0'; } /* Output mailbox list. */ count = 0; iter = ao2_iterator_init(mailboxes, AO2_ITERATOR_UNLINK); for (; (mailbox = ao2_iterator_next(&iter)); ast_mwi_mailbox_unref(mailbox)) { ++count; astman_append(s, "Event: MWIGet\r\n" "Mailbox: %s\r\n" "OldMessages: %u\r\n" "NewMessages: %u\r\n" "%s" "\r\n", ast_mwi_mailbox_get_id(mailbox), ast_mwi_mailbox_get_msgs_old(mailbox), ast_mwi_mailbox_get_msgs_new(mailbox), id_text); } ao2_iterator_destroy(&iter); ao2_ref(mailboxes, -1); astman_send_list_complete_start(s, m, "MWIGetComplete", count); astman_send_list_complete_end(s); return 0; }
static char *handle_mwi_update_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { struct ast_mwi_mailbox_object *mailbox; const char *mailbox_id; unsigned int num_new; unsigned int num_old; switch (cmd) { case CLI_INIT: e->command = "mwi update mailbox"; e->usage = "Usage: mwi update mailbox <mailbox_id> [<new> [<old>]]\n" " Update a specific external MWI mailbox.\n"; return NULL; case CLI_GENERATE: if (a->pos == 3) { return complete_mailbox(a->word, a->n); } return NULL; } if (a->argc < 4 || 6 < a->argc) { return CLI_SHOWUSAGE; } mailbox_id = a->argv[3]; num_new = 0; if (4 < a->argc) { const char *count_new = a->argv[4]; if (sscanf(count_new, "%u", &num_new) != 1) { ast_cli(a->fd, "Invalid NewMessages: '%s'.\n", count_new); return CLI_SHOWUSAGE; } } num_old = 0; if (5 < a->argc) { const char *count_old = a->argv[5]; if (sscanf(count_old, "%u", &num_old) != 1) { ast_cli(a->fd, "Invalid OldMessages: '%s'.\n", count_old); return CLI_SHOWUSAGE; } } mailbox = ast_mwi_mailbox_alloc(mailbox_id); if (mailbox) { ast_mwi_mailbox_set_msgs_new(mailbox, num_new); ast_mwi_mailbox_set_msgs_old(mailbox, num_old); if (ast_mwi_mailbox_update(mailbox)) { ast_cli(a->fd, "Could not update mailbox %s.\n", ast_sorcery_object_get_id(mailbox)); } else { ast_cli(a->fd, "Updated mailbox %s.\n", ast_sorcery_object_get_id(mailbox)); } ast_mwi_mailbox_unref(mailbox); } return CLI_SUCCESS; }