From 05e2f057484b17f7576b20d71a920e8caf9a8e77 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Mon, 13 Jan 2025 15:26:00 +0100 Subject: [PATCH] MT#61862 support bookworm 22.1.1~dfsg+~cs6.14.60671435-1~bpo12+1 * apps:*.c from upstream 22.1.1~dfsg+~cs6.14.60671435-1 * debian/patches: refresh and resolve conflicts Change-Id: I9a7dad84e06bc4e2834df71c9a3ecd955985d470 --- apps/app_playback.c | 14 +- apps/app_voicemail.c | 2233 +++++++++++++---- debian/patches/sipwise_define_module.patch | 4 +- .../sipwise_fix_compile_warnings.patch | 6 +- .../patches/sipwise_vm_add_actions_wmi.patch | 123 +- .../sipwise_vm_add_arabic_support.patch | 18 +- debian/patches/sipwise_vm_add_callid.patch | 288 ++- .../patches/sipwise_vm_add_pcre_support.patch | 20 +- .../sipwise_vm_app_playback_timezone.patch | 10 +- ...ipwise_vm_ast_load_realtime_use_uuid.patch | 14 +- ...e_vm_change_password_use_customer_id.patch | 4 +- .../sipwise_vm_envelope_behaviour.patch | 8 +- debian/patches/sipwise_vm_ext_timezone.patch | 14 +- .../sipwise_vm_find_user_by_alias.patch | 12 +- .../patches/sipwise_vm_fix_chan_usage.patch | 4 +- .../patches/sipwise_vm_fix_double_menu.patch | 4 +- .../sipwise_vm_fix_envelope_play.patch | 6 +- .../sipwise_vm_fix_odbc_retreive_file.patch | 8 +- .../patches/sipwise_vm_fix_prev_message.patch | 6 +- .../sipwise_vm_hebrew_language_fixups.patch | 4 +- .../patches/sipwise_vm_play_anonymous.patch | 4 +- ...lay_prompt_on_change_to_empty_folder.patch | 8 +- .../patches/sipwise_vm_pointers_malloc.patch | 4 +- .../patches/sipwise_vm_romanian_syntax.patch | 18 +- debian/patches/sipwise_vm_sms_notify.patch | 31 +- ...pwise_vm_store_message_add_diag_info.patch | 40 +- debian/patches/sipwise_vm_uuid_mailbox.patch | 214 +- .../sipwise_vm_vmnotify_ext_format.patch | 30 +- debian/patches/sipwise_vm_zonemessages.patch | 10 +- 29 files changed, 2316 insertions(+), 843 deletions(-) diff --git a/apps/app_playback.c b/apps/app_playback.c index 56c2a86..6b93b03 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -48,6 +48,13 @@ + Ampersand separated list of filenames. If the filename + is a relative filename (it does not begin with a slash), it + will be searched for in the Asterisk sounds directory. If the + filename is able to be parsed as a URL, Asterisk will + download the file and then begin playback on it. To include a + literal & in the URL you can enclose + the URL in single quotes. @@ -87,7 +94,7 @@ WaitExten (application) -- wait for digits from caller, optionally play music on hold - Background + BackGround WaitExten ControlPlayback stream file @@ -492,7 +499,7 @@ static int playback_exec(struct ast_channel *chan, const char *data) char *front; ast_stopstream(chan); - while (!res && (front = strsep(&back, "&"))) { + while (!res && (front = ast_strsep(&back, '&', AST_STRSEP_STRIP | AST_STRSEP_TRIM))) { if (option_say) res = say_full(chan, front, "", ast_channel_language(chan), NULL, -1, -1); else if (option_mix){ @@ -507,8 +514,7 @@ static int playback_exec(struct ast_channel *chan, const char *data) if (!res) { res = ast_waitstream(chan, ""); ast_stopstream(chan); - } - if (res) { + } else { if (!ast_check_hangup(chan)) { ast_log(LOG_WARNING, "Playback failed on %s for %s\n", ast_channel_name(chan), (char *)data); } diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 1aca59b..714e4d9 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -27,7 +27,7 @@ * * \par See also * \arg \ref voicemail.conf "Config_voicemail" - * \note For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage + * \note For information about voicemail IMAP storage, https://docs.asterisk.org/Configuration/Applications/Voicemail/IMAP-Voicemail-Storage/ * \ingroup applications * \todo This module requires res_adsi to load. This needs to be optional * during compilation. @@ -445,6 +445,123 @@ Otherwise, only a single mailbox will be polled for changes. + + + Show the mailbox contents of given voicemail user. + + + + + The context you want to check. + + + The mailbox you want to check. + + + + Retrieves the contents of the given voicemail user's mailbox. + + + + + Move Voicemail between mailbox folders of given user. + + + + + The context of the Voicemail you want to move. + + + The mailbox of the Voicemail you want to move. + + + The Folder containing the Voicemail you want to move. + + + The ID of the Voicemail you want to move. + + + The Folder you want to move the Voicemail to. + + + + Move a given Voicemail between Folders within a user's Mailbox. + + + + + Remove Voicemail from mailbox folder. + + + + + The context of the Voicemail you want to remove. + + + The mailbox of the Voicemail you want to remove. + + + The Folder containing the Voicemail you want to remove. + + + The ID of the Voicemail you want to remove. + + + + Remove a given Voicemail from a user's Mailbox Folder. + + + + + Forward Voicemail from one mailbox folder to another between given users. + + + + + The context of the Voicemail you want to move. + + + The mailbox of the Voicemail you want to move. + + + The Folder containing the Voicemail you want to move. + + + The ID of the Voicemail you want to move. + + + The context you want to move the Voicemail to. + + + The mailbox you want to move the Voicemail to. + + + The Folder you want to move the Voicemail to. + + + + Forward a given Voicemail from a user's Mailbox Folder to + another user's Mailbox Folder. Can be used to copy between + Folders within a mailbox by specifying the to context and user + as the same as the from. + + + + + Raised in response to a mailbox password change. + + + Mailbox context. + + + Mailbox name. + + + New password for mailbox. + + + + ***/ #ifdef IMAP_STORAGE @@ -571,10 +688,15 @@ static AST_LIST_HEAD_STATIC(vmstates, vmstate); #define VM_MESSAGEWRAP (1 << 17) /*!< Wrap around from the last message to the first, and vice-versa */ #define VM_FWDURGAUTO (1 << 18) /*!< Autoset of Urgent flag on forwarded Urgent messages set globally */ #define VM_EMAIL_EXT_RECS (1 << 19) /*!< Send voicemail emails when an external recording is added to a mailbox */ +#define VM_MARK_URGENT (1 << 20) /*!< After recording, permit the caller to mark the message as urgent */ +#define VM_ODBC_AUDIO_ON_DISK (1 << 21) /*!< When using ODBC, leave the message and greeting recordings on disk instead of moving them into the table */ + #define ERROR_LOCK_PATH -100 #define ERROR_MAX_MSGS -101 #define OPERATOR_EXIT 300 +#define MSGFILE_LEN (7) /*!< Length of the message file name: msgXXXX */ + enum vm_box { NEW_FOLDER = 0, OLD_FOLDER = 1, @@ -650,6 +772,18 @@ static const char * const mailbox_folders[] = { "Urgent", }; +/*! + * \brief Reload voicemail.conf + * \param reload Whether this is a reload as opposed to module load + * \param force Forcefully reload the config, even it has not changed + * \retval 0 on success, nonzero on failure + */ +static int load_config_force(int reload, int force); + +/*! \brief Forcibly reload voicemail.conf, even if it has not changed. + * This is necessary after running unit tests. */ +#define force_reload_config() load_config_force(1, 1) + static int load_config(int reload); #ifdef TEST_FRAMEWORK static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg); @@ -848,13 +982,16 @@ struct vm_state { #ifdef ODBC_STORAGE static char odbc_database[80] = "asterisk"; static char odbc_table[80] = "voicemessages"; -#define RETRIEVE(a,b,c,d) retrieve_file(a,b) -#define DISPOSE(a,b) remove_file(a,b) -#define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d) -#define EXISTS(a,b,c,d) (message_exists(a,b)) -#define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f)) -#define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f)) -#define DELETE(a,b,c,d) (delete_file(a,b)) +size_t odbc_table_len = sizeof(odbc_table); +#define COUNT(a, b) odbc_count_messages(a,b) +#define LAST_MSG_INDEX(a) odbc_last_message_index(a) +#define RETRIEVE(a,b,c,d) odbc_retrieve_message(a,b) +#define DISPOSE(a,b) odbc_remove_files(a,b) +#define STORE(a,b,c,d,e,f,g,h,i,j,k) odbc_store_message(a,b,c,d) +#define EXISTS(a,b,c,d) (odbc_message_exists(a,b)) +#define RENAME(a,b,c,d,e,f,g,h) (odbc_rename_message(a,b,c,d,e,f)) +#define COPY(a,b,c,d,e,f,g,h) (odbc_copy_message(a,b,c,d,e,f)) +#define DELETE(a,b,c,d) (odbc_delete_message(a,b)) #define UPDATE_MSG_ID(a, b, c, d, e, f) (odbc_update_msg_id((a), (b), (c))) #else #ifdef IMAP_STORAGE @@ -867,6 +1004,8 @@ static char odbc_table[80] = "voicemessages"; #define DELETE(a,b,c,d) (vm_imap_delete(a,b,d)) #define UPDATE_MSG_ID(a, b, c, d, e, f) (vm_imap_update_msg_id((a), (b), (c), (d), (e), (f))) #else +#define COUNT(a, b) count_messages(a,b) +#define LAST_MSG_INDEX(a) last_message_index(a) #define RETRIEVE(a,b,c,d) #define DISPOSE(a,b) #define STORE(a,b,c,d,e,f,g,h,i,j,k) @@ -1051,6 +1190,7 @@ static const char *substitute_escapes(const char *value); static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu); static void notify_new_state(struct ast_vm_user *vmu); static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char* event_name, const char* actionid); +static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char* event_name, const char* actionid); /*! @@ -1191,6 +1331,136 @@ static char *strip_control_and_high(const char *input, char *buf, size_t buflen) return buf; } +/* + * These macros are currently only used by the ODBC code but + * should be used anyplace we're allocating a PATH_MAX + * sized buffer for something which will be much smaller + * in practice. + */ +#ifdef ODBC_STORAGE +/*! + * \internal + * \brief Get the length needed for a message path base. + * + * \param dir The absolute path to a directory + * + * \note The directory provided should include all components + * down to the folder level. For example: + * /var/spool/asterisk/voicemail/default/1234/INBOX + * + * \returns Number of bytes needed for the message path base. + */ +static size_t get_msg_path_len(const char *dir) +{ + if (ast_strlen_zero(dir)) { + return 0; + } + /* dir + '/' + MSGFILE_LEN + '\0' */ + return strlen(dir) + 1 + MSGFILE_LEN + 1; +} + +/* + * The longest sound file extension we currently + * have is "siren14" which is 7 characters long + * but we'll make this 12 to be extra safe. + */ +#define MAX_SOUND_EXTEN_LEN 12 +/*! + * \internal + * \brief Get the length needed for a message sound or metadata file path. + * + * \param dir The absolute path to a directory + * + * \note The directory provided should include all components + * down to the folder level. For example: + * /var/spool/asterisk/voicemail/default/1234/INBOX + * + * \returns Number of bytes needed for the message sound or metadata file path. + */ +static size_t get_msg_path_ext_len(const char *dir) +{ + if (ast_strlen_zero(dir)) { + return 0; + } + /* dir + '/' + MSGFILE_LEN + extlen(including '.') + '\0' */ + return strlen(dir) + 1 + MSGFILE_LEN + MAX_SOUND_EXTEN_LEN + 1; +} + +/*! + * \internal + * \brief Allocate a buffer on the stack containing a message file path base. + * + * \param dir The absolute path to a directory + * \param msgnum The message number or -1 for a prompt file + * + * \note The returned buffer will automatically be freed when it + * goes out of scope. + * + * If passed (/var/spool/asterisk/voicemail/default/1234/INBOX, 0) + * the returned path would be: + * /var/spool/asterisk/voicemail/default/1234/INBOX/msg0000 + * + * If passed (/var/spool/asterisk/voicemail/default/1234/unavail, -1) + * the returned path would be: + * /var/spool/asterisk/voicemail/default/1234/unavail + * (no change) + * + * \returns A pointer to the buffer containing the path. + */ +#define MAKE_FILE_PTRA(dir, msgnum) \ +({ \ + size_t __len = get_msg_path_len(dir); \ + char *__var; \ + if (msgnum < 0) { \ + __var = ast_strdupa(dir); \ + } else { \ + __var = ast_alloca(__len); \ + snprintf(__var, __len, "%s/msg%04d", dir, msgnum); \ + } \ + __var; \ +}) + +/*! + * \internal + * \brief Allocate a buffer on the stack for a message sound or metadata file path. + * + * \param dir The absolute path to a directory + * \param msgnum The message number or -1 for a prompt file + * + * \note The returned buffer will automatically be freed when it + * goes out of scope. + * + * If passed (/var/spool/asterisk/voicemail/default/1234/INBOX, 0, "txt") + * the returned path would be: + * /var/spool/asterisk/voicemail/default/1234/INBOX/msg0000.txt + * + * If passed (/var/spool/asterisk/voicemail/default/1234/unavail, -1, "WAV") + * the returned path would be: + * /var/spool/asterisk/voicemail/default/1234/unavail.WAV + * + * The buffer returned has enough space that you can safely re-use it + * for other sound file extensions. For instance: + * + * char *fn = MAKE_FILE_PTRA(dir, msgnum); + * char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum, "txt"); + * char *fmt = "g722"; + * ...do domething with full_fn then re-use it... + * sprintf(full_fn, "%s.%s", fn, fmt); * Safe since the same dir and msgnum were used * + * + * \returns A pointer to the allocated buffer + */ +#define MAKE_FILE_EXT_PTRA(dir, msgnum, ext) \ +({ \ + size_t __len = get_msg_path_ext_len(dir); \ + char *__var = ast_alloca(__len); \ + if (msgnum < 0) { \ + snprintf(__var, __len, "%s.%s", dir, ext); \ + } else { \ + snprintf(__var, __len, "%s/msg%04d.%s", dir, msgnum, ext); \ + } \ + __var; \ +}) +#endif /*! * \brief Sets default voicemail system options to a voicemail user. @@ -1308,6 +1578,8 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v ast_set2_flag(vmu, ast_true(value), VM_SVMAIL); } else if (!strcasecmp(var, "review")){ ast_set2_flag(vmu, ast_true(value), VM_REVIEW); + } else if (!strcasecmp(var, "leaveurgent")){ + ast_set2_flag(vmu, ast_true(value), VM_MARK_URGENT); } else if (!strcasecmp(var, "tempgreetwarn")){ ast_set2_flag(vmu, ast_true(value), VM_TEMPGREETWARN); } else if (!strcasecmp(var, "messagewrap")){ @@ -1747,6 +2019,16 @@ static int reset_user_pw(const char *context, const char *mailbox, const char *n res = 0; } AST_LIST_UNLOCK(&users); + if (!res) { + struct ast_json *json_object; + + json_object = ast_json_pack("{s: s, s: s, s: s}", + "Context", S_OR(context, "default"), + "Mailbox", mailbox, + "NewPassword", newpass); + ast_manager_publish_event("VoicemailPasswordChange", EVENT_FLAG_SYSTEM | EVENT_FLAG_USER, json_object); + ast_json_unref(json_object); + } return res; } @@ -1790,7 +2072,7 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword) ast_copy_string(vmu->password, newpassword, sizeof(vmu->password)); break; } else { - ast_verb(4, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn); + ast_log(LOG_WARNING, "Writing voicemail password to file %s failed, falling back to config file\n", secretfn); } /* Fall-through */ case OPT_PWLOC_VOICEMAILCONF: @@ -2592,6 +2874,7 @@ static int messagecount(const char *mailbox_id, const char *folder) { char *context; char *mailbox; + int count; if (ast_strlen_zero(mailbox_id) || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) { @@ -2599,10 +2882,11 @@ static int messagecount(const char *mailbox_id, const char *folder) } if (ast_strlen_zero(folder) || !strcmp(folder, "INBOX")) { - return __messagecount(context, mailbox, "INBOX") + __messagecount(context, mailbox, "Urgent"); + count = __messagecount(context, mailbox, "INBOX") + __messagecount(context, mailbox, "Urgent"); } else { - return __messagecount(context, mailbox, folder); + count = __messagecount(context, mailbox, folder); } + return count < 0 ? 0 : count; } static int imap_store_file(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum, struct ast_channel *chan, struct ast_vm_user *vmu, char *fmt, int duration, struct vm_state *vms, const char *flag, const char *msg_id) @@ -2764,6 +3048,7 @@ static int inboxcount2(const char *mailbox_context, int *urgentmsgs, int *newmsg char *context; char *mb; char *cur; + int count = 0; if (newmsgs) *newmsgs = 0; if (oldmsgs) @@ -2813,21 +3098,24 @@ static int inboxcount2(const char *mailbox_context, int *urgentmsgs, int *newmsg ast_log(AST_LOG_ERROR, "Couldn't find mailbox %s in context %s\n", mailboxnc, context); return -1; } - if ((*newmsgs = __messagecount(context, mailboxnc, vmu->imapfolder)) < 0) { + if ((count = __messagecount(context, mailboxnc, vmu->imapfolder)) < 0) { free_user(vmu); return -1; } + *newmsgs = count; free_user(vmu); } if (oldmsgs) { - if ((*oldmsgs = __messagecount(context, mailboxnc, "Old")) < 0) { + if ((count = __messagecount(context, mailboxnc, "Old")) < 0) { return -1; } + *oldmsgs = count; } if (urgentmsgs) { - if ((*urgentmsgs = __messagecount(context, mailboxnc, "Urgent")) < 0) { + if ((count = __messagecount(context, mailboxnc, "Urgent")) < 0) { return -1; } + *urgentmsgs = count; } return 0; } @@ -2861,7 +3149,7 @@ static int has_voicemail(const char *mailbox, const char *folder) } else { context = "default"; } - return __messagecount(context, tmp, folder) ? 1 : 0; + return __messagecount(context, tmp, folder) > 0 ? 1 : 0; } /*! @@ -3738,6 +4026,43 @@ static int msg_id_incrementor; static void generate_msg_id(char *dst); #ifdef ODBC_STORAGE + +/*! + * \internal + * \brief Create a buffer containing the SQL statement with the table name inserted. + * + * \param __sql_fmt The SQL statement with a single '%s' where the table name should be inserted. + * + * \note The buffer is allocated on the stack and should not be freed. + * + * \return A pointer to a buffer containing the SQL statement with the table name inserted. + */ +#define MAKE_SQL_PTRA(__sql_fmt) \ +({ \ + /* The NULL terminator is included in odbc_table_len. */ \ + char *__sql = ast_alloca(strlen(__sql_fmt) + odbc_table_len); \ + sprintf(__sql, __sql_fmt, odbc_table); /* Safe */ \ + __sql; \ +}) + +/*! + * \internal + * \brief Create a buffer containing the SQL statement with the table name inserted twice. + * + * \param __sql_fmt The SQL statement with two '%s' where the table name should be inserted. + * + * \note The buffer is allocated on the stack and should not be freed. + * + * \return A pointer to a buffer containing the SQL statement with the table name inserted. + */ +#define MAKE_SQL_PTRA2(__sql_fmt) \ +({ \ + /* The NULL terminator is included in odbc_table_len. */ \ + char *__sql = ast_alloca(strlen(__sql_fmt) + (odbc_table_len * 2)); \ + sprintf(__sql, __sql_fmt, odbc_table, odbc_table); /* Safe */ \ + __sql; \ +}) + struct generic_prepare_struct { char *sql; int argc; @@ -3770,20 +4095,19 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data) static void odbc_update_msg_id(char *dir, int msg_num, char *msg_id) { SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?"); struct odbc_obj *obj; char msg_num_str[20]; char *argv[] = { msg_id, dir, msg_num_str }; struct generic_prepare_struct gps = { .sql = sql, .argc = 3, .argv = argv }; + SCOPE_ENTER(3, "dir: %s msg_num: %d msg_id: %s\n", dir, msg_num, msg_id); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(LOG_WARNING, "Unable to update message ID for message %d in %s\n", msg_num, dir); - return; + SCOPE_EXIT_LOG_RTN(LOG_WARNING, "Unable to update message ID for message %d in %s\n", msg_num, dir); } snprintf(msg_num_str, sizeof(msg_num_str), "%d", msg_num); - snprintf(sql, sizeof(sql), "UPDATE %s SET msg_id=? WHERE dir=? AND msgnum=?", odbc_table); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -3791,9 +4115,60 @@ static void odbc_update_msg_id(char *dir, int msg_num, char *msg_id) SQLFreeHandle(SQL_HANDLE_STMT, stmt); } ast_odbc_release_obj(obj); - return; + SCOPE_EXIT_RTN(); } +#define AUDIO_ON_DISK_MAGIC "AUDMAGIC" +#define AUDIO_ON_DISK_MAGIC_LEN 8 + +static void odbc_update_set_audmagic(char *dir, int msg_num) +{ + SQLHSTMT stmt; + char *sql = MAKE_SQL_PTRA("UPDATE %s SET recording=? WHERE dir=? AND msgnum=?"); + struct odbc_obj *obj; + SQLLEN datalen = AUDIO_ON_DISK_MAGIC_LEN; + SQLLEN indlen = datalen; + int res; + char msg_num_str[20]; + SCOPE_ENTER(3, "dir: %s msg_num: %d\n", dir, msg_num); + + obj = ast_odbc_request_obj(odbc_database, 0); + if (!obj) { + SCOPE_EXIT_LOG_RTN(LOG_WARNING, "Unable to request obj for message %d in %s\n", msg_num, dir); + } + + res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); + if (!SQL_SUCCEEDED(res)) { + ast_odbc_release_obj(obj); + SCOPE_EXIT_LOG_RTN(LOG_WARNING, "Unable to allocate stmt for message %d in %s\n", msg_num, dir); + } + + snprintf(msg_num_str, sizeof(msg_num_str), "%d", msg_num); + + SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, + datalen, 0, (void *) AUDIO_ON_DISK_MAGIC, + datalen, &indlen); + + SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, + strlen(dir), 0, (void *) dir, 0, NULL); + + SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, + strlen(msg_num_str), 0, (void *) msg_num_str, 0, NULL); + + res = ast_odbc_execute_sql(obj, stmt, sql); + if (!SQL_SUCCEEDED(res)) { + ast_log(LOG_WARNING, "Unable to execute stmt for message %d in %s\n", msg_num, dir); + ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute"); + } + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; + + ast_odbc_release_obj(obj); + SCOPE_EXIT_RTN("Done\n"); +} + +static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum); + /*! * \brief Retrieves a file from an ODBC data store. * \param dir the path to the file to be retrieved. @@ -3808,7 +4183,7 @@ static void odbc_update_msg_id(char *dir, int msg_num, char *msg_id) * * \return 0 on success, -1 on error. */ -static int retrieve_file(char *dir, int msgnum) +static int odbc_retrieve_message(char *dir, int msgnum) { int x = 0; int res; @@ -3817,7 +4192,7 @@ static int retrieve_file(char *dir, int msgnum) void *fdm = MAP_FAILED; SQLSMALLINT colcount = 0; SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("SELECT * FROM %s WHERE dir=? AND msgnum=?"); char fmt[80] = ""; char *c; char coltitle[256]; @@ -3829,18 +4204,22 @@ static int retrieve_file(char *dir, int msgnum) SQLLEN colsize2; FILE *f = NULL; char rowdata[80]; - char fn[PATH_MAX]; - char full_fn[PATH_MAX]; + char *fn = MAKE_FILE_PTRA(dir, msgnum); + char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum, "txt"); char msgnums[80]; + char *mailboxuser = NULL; + char *mailboxcontext = NULL; char msg_id[MSG_ID_LEN] = ""; char *argv[] = { dir, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; struct odbc_obj *obj; + int storage_conversion_to_disk = 0; + int storage_conversion_to_odbc = 0; + SCOPE_ENTER(3, "dir: %s msgnum: %d msgtype: %s\n", dir, msgnum, msgnum < 0 ? "Greeting" : "Message"); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } ast_copy_string(fmt, vmfmts, sizeof(fmt)); @@ -3851,21 +4230,14 @@ static int retrieve_file(char *dir, int msgnum) strcpy(fmt, "WAV"); snprintf(msgnums, sizeof(msgnums), "%d", msgnum); - if (msgnum > -1) - make_file(fn, sizeof(fn), dir, msgnum); - else - ast_copy_string(fn, dir, sizeof(fn)); - - /* Create the information file */ - snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); + ast_trace(-1, "Opening '%s' for writing\n", full_fn); if (!(f = fopen(full_fn, "w+"))) { ast_log(AST_LOG_WARNING, "Failed to open/create '%s'\n", full_fn); goto bail; } - snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt); - snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE dir=? AND msgnum=?", odbc_table); + sprintf(full_fn, "%s.%s", fn, fmt); /* Safe. We're just replacing the file exten. */ stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { @@ -3881,12 +4253,6 @@ static int retrieve_file(char *dir, int msgnum) goto bail_with_handle; } - fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, VOICEMAIL_FILE_MODE); - if (fd < 0) { - ast_log(AST_LOG_WARNING, "Failed to write '%s': %s\n", full_fn, strerror(errno)); - goto bail_with_handle; - } - res = SQLNumResultCols(stmt, &colcount); if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); @@ -3904,46 +4270,81 @@ static int retrieve_file(char *dir, int msgnum) ast_log(AST_LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); goto bail_with_handle; } + if (!strcasecmp(coltitle, "recording")) { off_t offset; + char tmp[1] = ""; + res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, 0, &colsize2); fdlen = colsize2; - if (fd > -1) { - char tmp[1] = ""; - lseek(fd, fdlen - 1, SEEK_SET); - if (write(fd, tmp, 1) != 1) { - close(fd); - fd = -1; - continue; + ast_trace(-1, "Audio size: %ld\n", colsize2); + if (colsize2 == AUDIO_ON_DISK_MAGIC_LEN) { + res = SQLGetData(stmt, x + 1, SQL_BINARY, rowdata, AUDIO_ON_DISK_MAGIC_LEN, NULL); + if (memcmp(rowdata, AUDIO_ON_DISK_MAGIC, AUDIO_ON_DISK_MAGIC_LEN) != 0) { + ast_log(AST_LOG_WARNING, "Invalid audio magic number '0x%02X%02X%02X%02X%02X%02X%02X%02X' for '%s'\n", + rowdata[0], rowdata[1], rowdata[2], rowdata[3], rowdata[4], rowdata[5], rowdata[6], + rowdata[7], full_fn); + goto bail_with_handle; } - /* Read out in small chunks */ - for (offset = 0; offset < colsize2; offset += CHUNKSIZE) { - if ((fdm = mmap(NULL, CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) { - ast_log(AST_LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno); - goto bail_with_handle; - } - res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL); - munmap(fdm, CHUNKSIZE); - if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - unlink(full_fn); - goto bail_with_handle; - } + ast_trace(-1, "Audio is stored on disk. No need to write '%s'\n", full_fn); + if (!ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + storage_conversion_to_odbc = 1; } - if (truncate(full_fn, fdlen) < 0) { - ast_log(LOG_WARNING, "Unable to truncate '%s': %s\n", full_fn, strerror(errno)); + + continue; + } + + ast_trace(-1, "Opening '%s' for writing\n", full_fn); + fd = open(full_fn, O_RDWR | O_CREAT | O_TRUNC, VOICEMAIL_FILE_MODE); + if (fd < 0) { + ast_log(AST_LOG_WARNING, "Failed to open '%s' for writing: %s\n", full_fn, strerror(errno)); + goto bail_with_handle; + } + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + storage_conversion_to_disk = 1; + } + + lseek(fd, fdlen - 1, SEEK_SET); + if (write(fd, tmp, 1) != 1) { + close(fd); + fd = -1; + continue; + } + /* Read out in small chunks */ + for (offset = 0; offset < colsize2; offset += CHUNKSIZE) { + if ((fdm = mmap(NULL, CHUNKSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == MAP_FAILED) { + ast_log(AST_LOG_WARNING, "Could not mmap the output file: %s (%d)\n", strerror(errno), errno); + goto bail_with_handle; } + res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL); + munmap(fdm, CHUNKSIZE); + if (!SQL_SUCCEEDED(res)) { + ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); + unlink(full_fn); + goto bail_with_handle; + } + } + if (truncate(full_fn, fdlen) < 0) { + ast_log(LOG_WARNING, "Unable to truncate '%s': %s\n", full_fn, strerror(errno)); } + ast_trace(-1, "Wrote %d bytes to '%s'\n", (int)fdlen, full_fn); } else { res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); if (res == SQL_NULL_DATA && !strcasecmp(coltitle, "msg_id")) { - /* Generate msg_id now, but don't store it until we're done with this - connection */ + /* + * Generate msg_id if there wasn't one, but don't store it until we're + * done with this connection. + */ generate_msg_id(msg_id); + ast_trace(-1, "msg_id was NULL. Generating new one: %s\n", msg_id); snprintf(rowdata, sizeof(rowdata), "%s", msg_id); + } else if (!strcasecmp(coltitle, "mailboxuser")) { + mailboxuser = ast_strdupa(rowdata); + } else if (!strcasecmp(coltitle, "mailboxcontext")) { + mailboxcontext = ast_strdupa(rowdata); } else if (res == SQL_NULL_DATA && !strcasecmp(coltitle, "category")) { /* Ignore null column value for category */ - ast_debug(3, "Ignoring null category column in ODBC voicemail retrieve_file.\n"); + ast_trace(-1, "Ignoring null category column in ODBC voicemail retrieve_file.\n"); continue; } else if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Get Data error! coltitle=%s\n[%s]\n\n", coltitle, sql); @@ -3973,39 +4374,55 @@ bail: odbc_update_msg_id(dir, msgnum, msg_id); } - return x - 1; + if (SQL_SUCCEEDED(res)) { + if (storage_conversion_to_disk) { + /* + * If we're currently storing audio on disk but there was pre-existing + * audio in the database, we need to update the database to set the + * 'recording' column to AUDIO_ON_DISK_MAGIC. + */ + SCOPE_CALL(-1, odbc_update_set_audmagic, dir, msgnum); + } + if (storage_conversion_to_odbc) { + /* + * If we're currently storing audio in the database but there was + * pre-existing audio on disk, we need to add the audio back + * into the database overwriting the AUDIO_ON_DISK_MAGIC + * magic number. + */ + SCOPE_CALL(-1, odbc_store_message, dir, mailboxuser, mailboxcontext, msgnum); + } + } + + SCOPE_EXIT_RTN_VALUE(x - 1, "Done. msg_id: %s RC: %d\n", msg_id, x - 1); } /*! * \brief Determines the highest message number in use for a given user and mailbox folder. - * \param vmu * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause. * * This method is used when mailboxes are stored in an ODBC back end. * Typical use to set the msgnum would be to take the value returned from this method and add one to it. * * \return the value of zero or greater to indicate the last message index in use, -1 to indicate none. - */ -static int last_message_index(struct ast_vm_user *vmu, char *dir) +static int odbc_last_message_index(char *dir) { int x = -1; int res; SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("SELECT msgnum FROM %s WHERE dir=? order by msgnum desc"); char rowdata[20]; char *argv[] = { dir }; struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv }; struct odbc_obj *obj; + SCOPE_ENTER(3, "dir: %s\n", dir); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } - snprintf(sql, sizeof(sql), "SELECT msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table); - stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -4015,7 +4432,7 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir) res = SQLFetch(stmt); if (!SQL_SUCCEEDED(res)) { if (res == SQL_NO_DATA) { - ast_log(AST_LOG_DEBUG, "Directory '%s' has no messages and therefore no index was retrieved.\n", dir); + ast_trace(-1, "Directory '%s' has no messages and therefore no index was retrieved.\n", dir); } else { ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); } @@ -4038,7 +4455,7 @@ bail_with_handle: bail: ast_odbc_release_obj(obj); - return x; + SCOPE_EXIT_RTN_VALUE(x, "Done. Last message index: %d\n", x); } /*! @@ -4050,26 +4467,25 @@ bail: * * \return greater than zero if the message exists, zero when the message does not exist or on error. */ -static int message_exists(char *dir, int msgnum) +static int odbc_message_exists(char *dir, int msgnum) { int x = 0; int res; SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?"); char rowdata[20]; char msgnums[20]; char *argv[] = { dir, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; struct odbc_obj *obj; + SCOPE_ENTER(3, "dir: %s msgnum: %d\n", dir, msgnum); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return 0; + SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } snprintf(msgnums, sizeof(msgnums), "%d", msgnum); - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=? AND msgnum=?", odbc_table); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -4097,7 +4513,7 @@ bail_with_handle: bail: ast_odbc_release_obj(obj); - return x; + SCOPE_EXIT_RTN_VALUE(x, "Done. Msg %s\n", x ? "exists" : "does not exist"); } /*! @@ -4109,24 +4525,23 @@ bail: * * \return The count of messages being zero or more, less than zero on error. */ -static int count_messages(struct ast_vm_user *vmu, char *dir) +static int odbc_count_messages(struct ast_vm_user *vmu, char *dir) { int x = -1; int res; SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("SELECT COUNT(*) FROM %s WHERE dir=?"); char rowdata[20]; char *argv[] = { dir }; struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv }; struct odbc_obj *obj; + SCOPE_ENTER(3, "dir: %s\n", dir); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir=?", odbc_table); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -4154,7 +4569,7 @@ bail_with_handle: bail: ast_odbc_release_obj(obj); - return x; + SCOPE_EXIT_RTN_VALUE(x, "Done. Count %d\n", x); } /*! @@ -4165,25 +4580,25 @@ bail: * This method is used when mailboxes are stored in an ODBC back end. * The specified message is directly deleted from the database 'voicemessages' table. */ -static void delete_file(const char *sdir, int smsg) +#define DELETE_SQL_FMT "DELETE FROM %s WHERE dir=? AND msgnum=?" +static void odbc_delete_message(const char *sdir, int smsg) { SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA(DELETE_SQL_FMT); char msgnums[20]; char *argv[] = { NULL, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; struct odbc_obj *obj; + SCOPE_ENTER(3, "sdir: %s smsg: %d\n", sdir, smsg); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + SCOPE_EXIT_LOG_RTN(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } argv[0] = ast_strdupa(sdir); snprintf(msgnums, sizeof(msgnums), "%d", smsg); - snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE dir=? AND msgnum=?", odbc_table); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -4192,7 +4607,13 @@ static void delete_file(const char *sdir, int smsg) } ast_odbc_release_obj(obj); - return; + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + char *src_fn = MAKE_FILE_PTRA(sdir, smsg); + ast_trace(-1, "Audio stored on disk. Deleting '%s'\n", src_fn); + ast_filedelete(src_fn, NULL); + } + + SCOPE_EXIT_RTN("Done\n"); } /*! @@ -4206,28 +4627,32 @@ static void delete_file(const char *sdir, int smsg) * * This method is used for the COPY macro when mailboxes are stored in an ODBC back end. */ -static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext) +#define COPY_SQL_FMT "INSERT INTO %s (dir, msgnum, msg_id, context, callerid, origtime, " \ + "duration, recording, flag, mailboxuser, mailboxcontext) " \ + "SELECT ?,?,msg_id,context,callerid,origtime,duration,recording,flag,?,? " \ + "FROM %s WHERE dir=? AND msgnum=?" +static void odbc_copy_message(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext) { SQLHSTMT stmt; - char sql[512]; + char *sql = MAKE_SQL_PTRA2(COPY_SQL_FMT); char msgnums[20]; char msgnumd[20]; - char msg_id[MSG_ID_LEN]; struct odbc_obj *obj; - char *argv[] = { ddir, msgnumd, msg_id, dmailboxuser, dmailboxcontext, sdir, msgnums }; - struct generic_prepare_struct gps = { .sql = sql, .argc = 7, .argv = argv }; + char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums }; + struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv }; + SCOPE_ENTER(3, "sdir: %s smsg: %d duser: %s dcontext: %s ddir: %s dmsg: %d\n", + sdir, smsg, dmailboxuser, dmailboxcontext, ddir, dmsg); + + SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg); - generate_msg_id(msg_id); - delete_file(ddir, dmsg); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + SCOPE_EXIT_LOG_RTN(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } snprintf(msgnums, sizeof(msgnums), "%d", smsg); snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg); - snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, msg_id, context, macrocontext, callerid, origtime, duration, recording, flag, mailboxuser, mailboxcontext) SELECT ?,?,?,context,macrocontext,callerid,origtime,duration,recording,flag,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table); + stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql); @@ -4235,18 +4660,25 @@ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailbox SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); - return; + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + char *src_fn = MAKE_FILE_PTRA(sdir, smsg); + char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg); + + ast_trace(-1, "Audio stored on disk. Copying '%s' to '%s'\n", src_fn, dst_fn); + ast_filecopy(src_fn, dst_fn, NULL); + } + + SCOPE_EXIT_RTN("Done\n"); } +#undef COPY_SQL_FMT struct insert_data { - char *sql; const char *dir; const char *msgnums; void *data; SQLLEN datalen; SQLLEN indlen; const char *context; - const char *macrocontext; const char *callerid; const char *origtime; const char *duration; @@ -4257,41 +4689,72 @@ struct insert_data { const char *msg_id; }; -static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) +#define STORE_SQL_FMT_CAT "INSERT INTO %s (dir, msgnum, recording, context, callerid, " \ + "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, category) " \ + "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)" +#define STORE_SQL_FMT "INSERT INTO %s (dir, msgnum, recording, context, callerid, "\ + "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id) "\ + "VALUES (?,?,?,?,?,?,?,?,?,?,?)" + +static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) { struct insert_data *data = vdata; + char *insert_sql; + char *delete_sql; int res; SQLHSTMT stmt; + SCOPE_ENTER(3, "dir: %s msgnums: %s msg_id: %s\n", data->dir, data->msgnums, + data->msg_id); res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); - return NULL; + SCOPE_EXIT_LOG_RTN_VALUE(NULL, AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); + } + + /* Delete any existing row with the same dir and msgnum */ + delete_sql = MAKE_SQL_PTRA(DELETE_SQL_FMT); + SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (void *) data->dir, 0, NULL); + SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (void *) data->msgnums, 0, NULL); + res = ast_odbc_execute_sql(obj, stmt, delete_sql); + if (!SQL_SUCCEEDED(res)) { + ast_trace(-1, "There wasn't an existing row. Good.\n"); + } else { + ast_trace(-1, "There WAS an existing row. This is OK if we're replacing a message.\n"); + } + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + stmt = NULL; + + res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); + if (!SQL_SUCCEEDED(res)) { + SCOPE_EXIT_LOG_RTN_VALUE(NULL, AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); } SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->dir), 0, (void *) data->dir, 0, NULL); SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msgnums), 0, (void *) data->msgnums, 0, NULL); SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_LONGVARBINARY, data->datalen, 0, (void *) data->data, data->datalen, &data->indlen); SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->context), 0, (void *) data->context, 0, NULL); - SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->macrocontext), 0, (void *) data->macrocontext, 0, NULL); - SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (void *) data->callerid, 0, NULL); - SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (void *) data->origtime, 0, NULL); - SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (void *) data->duration, 0, NULL); - SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (void *) data->mailboxuser, 0, NULL); - SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (void *) data->mailboxcontext, 0, NULL); - SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (void *) data->flag, 0, NULL); - SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (void *) data->msg_id, 0, NULL); + SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->callerid), 0, (void *) data->callerid, 0, NULL); + SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->origtime), 0, (void *) data->origtime, 0, NULL); + SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->duration), 0, (void *) data->duration, 0, NULL); + SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxuser), 0, (void *) data->mailboxuser, 0, NULL); + SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (void *) data->mailboxcontext, 0, NULL); + SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (void *) data->flag, 0, NULL); + SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (void *) data->msg_id, 0, NULL); if (!ast_strlen_zero(data->category)) { - SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (void *) data->category, 0, NULL); + insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT_CAT); + SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (void *) data->category, 0, NULL); + } else { + insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT); } - res = ast_odbc_execute_sql(obj, stmt, data->sql); + res = ast_odbc_execute_sql(obj, stmt, insert_sql); if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Direct Execute failed!\n"); + ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n", insert_sql); + ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute"); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return NULL; + stmt = NULL; } - return stmt; + SCOPE_EXIT_RTN_VALUE(stmt, "%s\n", stmt ? "Success" : "Failed"); } /*! @@ -4307,31 +4770,29 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) * * \return the zero on success -1 on error. */ -static int store_file(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum) +static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum) { int res = 0; int fd = -1; void *fdm = MAP_FAILED; off_t fdlen = -1; SQLHSTMT stmt; - char sql[PATH_MAX]; char msgnums[20]; - char fn[PATH_MAX]; - char full_fn[PATH_MAX]; + char *fn = MAKE_FILE_PTRA(dir, msgnum); + char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum, "txt"); char fmt[80]=""; char *c; struct ast_config *cfg = NULL; struct odbc_obj *obj; - struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext, - .context = "", .macrocontext = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "" }; + struct insert_data idata = { .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext, + .context = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "" }; struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; - - delete_file(dir, msgnum); + SCOPE_ENTER(3, "dir: %s user: %s context: %s msgnum: %d msgtype: %s\n", + dir, mailboxuser, mailboxcontext, msgnum, msgnum < 0 ? "Greeting" : "Message"); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } do { @@ -4341,27 +4802,41 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail *c = '\0'; if (!strcasecmp(fmt, "wav49")) strcpy(fmt, "WAV"); + + ast_trace(-1, "Formats: %s Using format: '%s'\n", vmfmts, fmt); snprintf(msgnums, sizeof(msgnums), "%d", msgnum); - if (msgnum > -1) - make_file(fn, sizeof(fn), dir, msgnum); - else - ast_copy_string(fn, dir, sizeof(fn)); - snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); + + ast_trace(-1, "Base path: '%s'\n", fn); + ast_trace(-1, "Opening '%s'\n", full_fn); cfg = ast_config_load(full_fn, config_flags); - snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt); - fd = open(full_fn, O_RDWR); - if (fd < 0) { - ast_log(AST_LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno)); - res = -1; - break; + if (!valid_config(cfg)) { + if (msgnum < 0) { + ast_trace(-1, "No information file found for '%s'. This is a greeting so this is OK.\n", full_fn); + } else { + ast_log(AST_LOG_WARNING, "Failed to open '%s'\n", full_fn); + res = -1; + break; + } + } + + sprintf(full_fn, "%s.%s", fn, fmt); /* Safe */ + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + ast_trace(-1, "Audio stored on disk. No need to open '%s'\n", full_fn); + } else { + ast_trace(-1, "Opening '%s'\n", full_fn); + fd = open(full_fn, O_RDWR); + if (fd < 0) { + ast_log(AST_LOG_WARNING, "Open of sound file '%s' failed: %s\n", full_fn, strerror(errno)); + res = -1; + break; + } } + if (valid_config(cfg)) { + ast_trace(-1, "Using information file '%s'\n", fn); if (!(idata.context = ast_variable_retrieve(cfg, "message", "context"))) { idata.context = ""; } - if (!(idata.macrocontext = ast_variable_retrieve(cfg, "message", "macrocontext"))) { - idata.macrocontext = ""; - } if (!(idata.callerid = ast_variable_retrieve(cfg, "message", "callerid"))) { idata.callerid = ""; } @@ -4381,25 +4856,28 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail idata.msg_id = ""; } } - fdlen = lseek(fd, 0, SEEK_END); - if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) { - ast_log(AST_LOG_WARNING, "Failed to process sound file '%s': %s\n", full_fn, strerror(errno)); - res = -1; - break; - } - fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (fdm == MAP_FAILED) { - ast_log(AST_LOG_WARNING, "Memory map failed for sound file '%s'!\n", full_fn); - res = -1; - break; - } - idata.data = fdm; - idata.datalen = idata.indlen = fdlen; - if (!ast_strlen_zero(idata.category)) - snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); - else - snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); + if (fd < 0) { + ast_trace(-1, "Audio stored on disk. Not reading sound file '%s' but setting magic number.\n", full_fn); + idata.data = AUDIO_ON_DISK_MAGIC; + idata.datalen = idata.indlen = AUDIO_ON_DISK_MAGIC_LEN; + } else { + ast_trace(-1, "Reading sound file '%s'\n", full_fn); + fdlen = lseek(fd, 0, SEEK_END); + if (fdlen < 0 || lseek(fd, 0, SEEK_SET) < 0) { + ast_log(AST_LOG_WARNING, "Failed to process sound file '%s': %s\n", full_fn, strerror(errno)); + res = -1; + break; + } + fdm = mmap(NULL, fdlen, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (fdm == MAP_FAILED) { + ast_log(AST_LOG_WARNING, "Memory map failed for sound file '%s'!\n", full_fn); + res = -1; + break; + } + idata.data = fdm; + idata.datalen = idata.indlen = fdlen; + } if (ast_strlen_zero(idata.origtime)) { idata.origtime = "0"; @@ -4409,10 +4887,9 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail idata.duration = "0"; } - if ((stmt = ast_odbc_direct_execute(obj, insert_data_cb, &idata))) { + if ((stmt = ast_odbc_direct_execute(obj, odbc_insert_data_cb, &idata))) { SQLFreeHandle(SQL_HANDLE_STMT, stmt); } else { - ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); res = -1; } } while (0); @@ -4425,8 +4902,10 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail munmap(fdm, fdlen); if (fd > -1) close(fd); - return res; + SCOPE_EXIT_RTN_VALUE(res, "%s\n", res ? "Failed" : "Success"); } +#undef STORE_SQL_FMT +#undef STORE_SQL_FMT_CAT /*! * \brief Renames a message in a mailbox folder. @@ -4441,34 +4920,44 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail * The is usually used to resequence the messages in the mailbox, such as to delete messag index 0, it would be called successively to slide all the other messages down one index. * But in theory, because the SQL query performs an update on (dir, msgnum, mailboxuser, mailboxcontext) in the database, it should be possible to have the message relocated to another mailbox or context as well. */ -static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg) +static void odbc_rename_message(char *sdir, int smsg, char *mailboxuser, char *mailboxcontext, char *ddir, int dmsg) { SQLHSTMT stmt; - char sql[PATH_MAX]; + char *sql = MAKE_SQL_PTRA("UPDATE %s SET dir=?, msgnum=? WHERE mailboxuser=? AND mailboxcontext=? AND dir=? AND msgnum=?"); char msgnums[20]; char msgnumd[20]; struct odbc_obj *obj; char *argv[] = { ddir, msgnumd, mailboxuser, mailboxcontext, sdir, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv }; + SCOPE_ENTER(3, "sdir: %s smsg: %d user: %s context: %s ddir: %s dmsg: %d\n", sdir, smsg, + mailboxuser, mailboxcontext, ddir, dmsg); - delete_file(ddir, dmsg); + SCOPE_CALL(-1, odbc_delete_message, ddir, dmsg); obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + SCOPE_EXIT_LOG_RTN(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } snprintf(msgnums, sizeof(msgnums), "%d", smsg); snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg); - snprintf(sql, sizeof(sql), "UPDATE %s SET dir=?, msgnum=?, mailboxuser=?, mailboxcontext=? WHERE dir=? AND msgnum=?", odbc_table); + stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); else SQLFreeHandle(SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); - return; + + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + char *src_fn = MAKE_FILE_PTRA(sdir, smsg); + char *dst_fn = MAKE_FILE_PTRA(ddir, dmsg); + + ast_trace(-1, "Recordings stored on disk. Renaming '%s' to '%s'\n", src_fn, dst_fn); + ast_filerename(src_fn, dst_fn, NULL); + } + + SCOPE_EXIT_RTN("Done.\n"); } /*! @@ -4482,21 +4971,23 @@ static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxco * Note that this does not remove the message from the mailbox folders, to do that we would use delete_file(). * \return zero on success, -1 on error. */ -static int remove_file(char *dir, int msgnum) +static int odbc_remove_files(char *dir, int msgnum) { - char fn[PATH_MAX]; - char full_fn[PATH_MAX]; - char msgnums[80]; + char *fn = MAKE_FILE_PTRA(dir, msgnum); + char *full_fn = MAKE_FILE_EXT_PTRA(dir, msgnum, "txt"); + SCOPE_ENTER(3, "dir: %s msgnum: %d\n", dir, msgnum); - if (msgnum > -1) { - snprintf(msgnums, sizeof(msgnums), "%d", msgnum); - make_file(fn, sizeof(fn), dir, msgnum); - } else - ast_copy_string(fn, dir, sizeof(fn)); - ast_filedelete(fn, NULL); - snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); + if (ast_test_flag((&globalflags), VM_ODBC_AUDIO_ON_DISK)) { + ast_trace(-1, "Audio stored on disk. Keeping '%s' sound files\n", fn); + } else { + ast_trace(-1, "Audio stored in ODBC. Removing '%s' sound files\n", fn); + ast_filedelete(fn, NULL); + } + + /* Always remove the information file */ + ast_trace(-1, "Removing '%s' information file\n", full_fn); unlink(full_fn); - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Done.\n"); } #else #ifndef IMAP_STORAGE @@ -4554,7 +5045,6 @@ static void rename_file(char *sfn, char *dfn) /*! * \brief Determines the highest message number in use for a given user and mailbox folder. - * \param vmu * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause. * * This method is used when mailboxes are stored on the filesystem. (not ODBC and not IMAP). @@ -4563,7 +5053,7 @@ static void rename_file(char *sfn, char *dfn) * \note Should always be called with a lock already set on dir. * \return the value of zero or greaterto indicate the last message index in use, -1 to indicate none. */ -static int last_message_index(struct ast_vm_user *vmu, char *dir) +static int last_message_index(char *dir) { int x; unsigned char map[MAXMSGLIMIT] = ""; @@ -4590,12 +5080,8 @@ static int last_message_index(struct ast_vm_user *vmu, char *dir) } closedir(msgdir); - for (x = 0; x < vmu->maxmsg; x++) { - if (map[x] == 1) { - stopcount--; - } else if (map[x] == 0 && !stopcount) { - break; - } + for (x = 0; x < MAXMSGLIMIT && stopcount; x++) { + stopcount -= map[x]; } return x - 1; @@ -4683,7 +5169,7 @@ static void copy_plain_file(char *frompath, char *topath) { char frompath2[PATH_MAX], topath2[PATH_MAX]; struct ast_variable *tmp, *var = NULL; - const char *origmailbox = "", *context = "", *macrocontext = "", *exten = ""; + const char *origmailbox = "", *context = "", *exten = ""; const char *priority = "", *callerchan = "", *callerid = "", *origdate = ""; const char *origtime = "", *category = "", *duration = ""; @@ -4699,8 +5185,6 @@ static void copy_plain_file(char *frompath, char *topath) origmailbox = tmp->value; } else if (!strcasecmp(tmp->name, "context")) { context = tmp->value; - } else if (!strcasecmp(tmp->name, "macrocontext")) { - macrocontext = tmp->value; } else if (!strcasecmp(tmp->name, "exten")) { exten = tmp->value; } else if (!strcasecmp(tmp->name, "priority")) { @@ -4719,7 +5203,7 @@ static void copy_plain_file(char *frompath, char *topath) duration = tmp->value; } } - ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "macrocontext", macrocontext, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, SENTINEL); + ast_store_realtime("voicemail_data", "filename", topath, "origmailbox", origmailbox, "context", context, "exten", exten, "priority", priority, "callerchan", callerchan, "callerid", callerid, "origdate", origdate, "origtime", origtime, "category", category, "duration", duration, SENTINEL); } copy(frompath2, topath2); ast_variables_destroy(var); @@ -4738,6 +5222,8 @@ static int vm_delete(char *file) { char *txt; int txtsize = 0; + int res = 0; + SCOPE_ENTER(3, "file: %s\n", file); txtsize = (strlen(file) + 5)*sizeof(char); txt = ast_alloca(txtsize); @@ -4748,8 +5234,11 @@ static int vm_delete(char *file) ast_destroy_realtime("voicemail_data", "filename", file, SENTINEL); } snprintf(txt, txtsize, "%s.txt", file); + ast_trace(-1, "unlinking '%s'\n", txt); unlink(txt); - return ast_filedelete(file, NULL); + ast_trace(-1, "deleting sound files '%s'\n", file); + res = ast_filedelete(file, NULL); + SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res); } static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag) @@ -5544,12 +6033,15 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char } } else { if (ast_strlen_zero(flag)) { - fprintf(p, "Subject: New VM\n\n"); + fprintf(p, "Subject: New VM" ENDL); } else { - fprintf(p, "Subject: New %s VM\n\n", flag); + fprintf(p, "Subject: New %s VM" ENDL, flag); } } + /* End of headers */ + fputs(ENDL, p); + if (pagerbody) { struct ast_channel *ast; if ((ast = ast_dummy_channel_alloc())) { @@ -5633,48 +6125,49 @@ static void free_zone(struct vm_zone *z) } #ifdef ODBC_STORAGE - +#define COUNT_MSGS_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'" static int count_messages_in_folder(struct odbc_obj *odbc, const char *context, const char *mailbox, const char *folder, int *messages) { int res; - char sql[PATH_MAX]; + char sql[sizeof(COUNT_MSGS_SQL_FMT) + odbc_table_len + strlen(VM_SPOOL_DIR) + + strlen(context) + strlen(mailbox) + strlen(folder)]; char rowdata[20]; SQLHSTMT stmt = NULL; struct generic_prepare_struct gps = { .sql = sql, .argc = 0 }; + SCOPE_ENTER(3, "context: %s mb: %s folder: %s", context, mailbox, folder); if (!messages) { - return 0; + SCOPE_EXIT_RTN_VALUE(0, "No messages pointer\n"); } - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder); + snprintf(sql, sizeof(sql), COUNT_MSGS_SQL_FMT, odbc_table, VM_SPOOL_DIR, context, mailbox, folder); if (!(stmt = ast_odbc_prepare_and_execute(odbc, generic_prepare, &gps))) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); - return 1; + SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); } res = SQLFetch(stmt); if (!SQL_SUCCEEDED(res)) { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return 1; + SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); if (!SQL_SUCCEEDED(res)) { - ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return 1; + SCOPE_EXIT_LOG_RTN_VALUE(1, LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); } *messages = atoi(rowdata); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return 0; + SCOPE_EXIT_RTN_VALUE(0, "messages: %d\n", *messages); } +#undef COUNT_MSGS_SQL_FMT static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) { char tmp[PATH_MAX] = ""; struct odbc_obj *obj; char *context; + SCOPE_ENTER(3, "mb: %s", mailbox); if (newmsgs) *newmsgs = 0; @@ -5684,8 +6177,9 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * *urgentmsgs = 0; /* If no mailbox, return immediately */ - if (ast_strlen_zero(mailbox)) - return 0; + if (ast_strlen_zero(mailbox)) { + SCOPE_EXIT_RTN_VALUE(0, "No mailbox\n"); + } ast_copy_string(tmp, mailbox, sizeof(tmp)); @@ -5694,7 +6188,7 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * char *next, *remaining = tmp; while ((next = strsep(&remaining, " ,"))) { if (inboxcount2(next, urgentmsgs ? &u : NULL, &n, &o)) { - return -1; + SCOPE_EXIT_RTN_VALUE(-1, "Failed to obtain message count for mailbox %s\n", next); } if (urgentmsgs) { *urgentmsgs += u; @@ -5706,7 +6200,7 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * *oldmsgs += o; } } - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0); } context = strchr(tmp, '@'); @@ -5718,8 +6212,7 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } if (count_messages_in_folder(obj, context, tmp, "INBOX", newmsgs) @@ -5730,7 +6223,7 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * } ast_odbc_release_obj(obj); - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Urgent: %d New: %d Old: %d\n", urgentmsgs ? *urgentmsgs : 0, newmsgs ? *newmsgs : 0, oldmsgs ? *oldmsgs : 0); } /*! @@ -5741,6 +6234,8 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * * This method is used when ODBC backend is used. * \return The number of messages in this mailbox folder (zero or more). */ +#define MSGCOUNT_SQL_FMT_INBOX "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/INBOX' OR dir = '%s%s/%s/Urgent'" +#define MSGCOUNT_SQL_FMT "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'" static int messagecount(const char *mailbox_id, const char *folder) { struct odbc_obj *obj = NULL; @@ -5749,14 +6244,14 @@ static int messagecount(const char *mailbox_id, const char *folder) int nummsgs = 0; int res; SQLHSTMT stmt = NULL; - char sql[PATH_MAX]; char rowdata[20]; - struct generic_prepare_struct gps = { .sql = sql, .argc = 0 }; + struct generic_prepare_struct gps = { .argc = 0 }; + SCOPE_ENTER(3, "mb: %s folder: %s", mailbox_id, folder); /* If no mailbox, return immediately */ if (ast_strlen_zero(mailbox_id) || separate_mailbox(ast_strdupa(mailbox_id), &mailbox, &context)) { - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Couldn't parse mailbox\n"); } if (ast_strlen_zero(folder)) { @@ -5765,29 +6260,32 @@ static int messagecount(const char *mailbox_id, const char *folder) obj = ast_odbc_request_obj(odbc_database, 0); if (!obj) { - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return 0; + SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); } if (!strcmp(folder, "INBOX")) { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/INBOX' OR dir = '%s%s/%s/Urgent'", odbc_table, VM_SPOOL_DIR, context, mailbox, VM_SPOOL_DIR, context, mailbox); + res = ast_asprintf(&gps.sql, MSGCOUNT_SQL_FMT_INBOX, odbc_table, VM_SPOOL_DIR, context, mailbox, VM_SPOOL_DIR, context, mailbox); } else { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder); + res = ast_asprintf(&gps.sql, MSGCOUNT_SQL_FMT, odbc_table, VM_SPOOL_DIR, context, mailbox, folder); + } + if (res <= 0) { + SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "Failed to allocate memory for SQL statement for '%s'!\n", odbc_database); } + ast_trace(-1, "SQL: %s\n", gps.sql); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { - ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); + ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", gps.sql); goto bail; } res = SQLFetch(stmt); if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); + ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", gps.sql); goto bail_with_handle; } res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); + ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", gps.sql); goto bail_with_handle; } nummsgs = atoi(rowdata); @@ -5797,8 +6295,11 @@ bail_with_handle: bail: ast_odbc_release_obj(obj); - return nummsgs; + ast_free(gps.sql); + SCOPE_EXIT_RTN_VALUE(nummsgs, "Messages: %d\n", nummsgs); } +#undef MSGCOUNT_SQL_FMT +#undef MSGCOUNT_SQL_FMT_INBOX /*! * \brief Determines if the given folder has messages. @@ -5839,13 +6340,17 @@ static int has_voicemail(const char *mailboxes, const char *folder) * * \return zero on success, -1 on error. */ -static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag, const char *dest_folder) +static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int imbox, int msgnum, + long duration, struct ast_vm_user *recip, char *fmt, char *dir, const char *flag, + const char *dest_folder) { char fromdir[PATH_MAX], todir[PATH_MAX], frompath[PATH_MAX], topath[PATH_MAX]; const char *frombox = mbox(vmu, imbox); const char *userfolder; int recipmsgnum; int res = 0; + SCOPE_ENTER(3, "mb: %s imb: %d msgnum: %d recip: %s dir: %s dest_folder: %s", + vmu->mailbox, imbox, msgnum, recip->mailbox, dir, dest_folder); ast_log(AST_LOG_NOTICE, "Copying message from %s@%s to %s@%s\n", vmu->mailbox, vmu->context, recip->mailbox, recip->context); @@ -5858,35 +6363,43 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i } create_dirpath(todir, sizeof(todir), recip->context, recip->mailbox, userfolder); + ast_trace(-1, "todir: %s\n", todir); if (!dir) make_dir(fromdir, sizeof(fromdir), vmu->context, vmu->mailbox, frombox); else ast_copy_string(fromdir, dir, sizeof(fromdir)); + ast_trace(-1, "fromdir: %s\n", fromdir); + make_file(frompath, sizeof(frompath), fromdir, msgnum); + ast_trace(-1, "frompath: %s\n", frompath); + make_dir(todir, sizeof(todir), recip->context, recip->mailbox, userfolder); + ast_trace(-1, "todir: %s\n", todir); - if (vm_lock_path(todir)) - return ERROR_LOCK_PATH; + if (vm_lock_path(todir)) { + SCOPE_EXIT_RTN_VALUE(ERROR_LOCK_PATH); + } + + recipmsgnum = LAST_MSG_INDEX(todir) + 1; + ast_trace(-1, "recip msgnum: %d\n", recipmsgnum); - recipmsgnum = last_message_index(recip, todir) + 1; if (recipmsgnum < recip->maxmsg - (imbox ? 0 : inprocess_count(vmu->mailbox, vmu->context, 0))) { + int exists = 0; + make_file(topath, sizeof(topath), todir, recipmsgnum); -#ifndef ODBC_STORAGE - if (EXISTS(fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : "")) { - COPY(fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath); + ast_trace(-1, "topath: %s\n", topath); + + exists = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, fromdir, msgnum, frompath, chan ? ast_channel_language(chan) : ""); + if (exists) { + SCOPE_CALL(-1, COPY, fromdir, msgnum, todir, recipmsgnum, recip->mailbox, recip->context, frompath, topath); } else { -#endif - /* If we are prepending a message for ODBC, then the message already - * exists in the database, but we want to force copying from the - * filesystem (since only the FS contains the prepend). */ - copy_plain_file(frompath, topath); - STORE(todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL); - vm_delete(topath); -#ifndef ODBC_STORAGE + SCOPE_CALL(-1, copy_plain_file,frompath, topath); + SCOPE_CALL(-1, STORE, todir, recip->mailbox, recip->context, recipmsgnum, chan, recip, fmt, duration, NULL, NULL, NULL); + SCOPE_CALL(-1, vm_delete, topath); + } -#endif } else { ast_log(AST_LOG_ERROR, "Recipient mailbox %s@%s is full\n", recip->mailbox, recip->context); res = -1; @@ -5900,7 +6413,7 @@ static int copy_message(struct ast_channel *chan, struct ast_vm_user *vmu, int i flag); } - return res; + SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res); } #endif #if !(defined(IMAP_STORAGE) || defined(ODBC_STORAGE)) @@ -6190,7 +6703,6 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) #ifdef IMAP_STORAGE struct vm_state *vms = NULL; char ext_context[256] = ""; - char *fmt = ast_strdupa(recdata->recording_ext); int newmsgs = 0; int oldmsgs = 0; #endif @@ -6270,7 +6782,6 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) "[message]\n" "origmailbox=%s\n" "context=%s\n" - "macrocontext=%s\n" "exten=%s\n" "rdnis=Unknown\n" "priority=%d\n" @@ -6285,7 +6796,6 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) recdata->mailbox, S_OR(recdata->call_context, ""), - S_OR(recdata->call_macrocontext, ""), S_OR(recdata->call_extension, ""), recdata->call_priority, S_OR(recdata->call_callerchan, "Unknown"), @@ -6358,9 +6868,9 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) #else /* Check to see if the mailbox is full for ODBC/File storage */ - ast_debug(3, "mailbox = %d : inprocess = %d\n", count_messages(recipient, dir), + ast_debug(3, "mailbox = %d : inprocess = %d\n", COUNT(recipient, dir), inprocess_count(recipient->mailbox, recipient->context, 0)); - if (count_messages(recipient, dir) > recipient->maxmsg - inprocess_count(recipient->mailbox, recipient->context, +1)) { + if (COUNT(recipient, dir) > recipient->maxmsg - inprocess_count(recipient->mailbox, recipient->context, +1)) { ast_log(AST_LOG_WARNING, "Didn't copy to voicemail. Mailbox for %s@%s is full.\n", recipient->mailbox, recipient->context); inprocess_count(recipient->mailbox, recipient->context, -1); free_user(recipient); @@ -6368,7 +6878,7 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) return -1; } - msgnum = last_message_index(recipient, dir) + 1; + msgnum = LAST_MSG_INDEX(dir) + 1; #endif /* Lock the directory receiving the voicemail since we want it to still exist when we attempt to copy the voicemail. @@ -6432,7 +6942,6 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) ast_store_realtime("voicemail_data", "origmailbox", recdata->mailbox, "context", S_OR(recdata->context, ""), - "macrocontext", S_OR(recdata->call_macrocontext, ""), "exten", S_OR(recdata->call_extension, ""), "priority", recdata->call_priority, "callerchan", S_OR(recdata->call_callerchan, "Unknown"), @@ -6500,8 +7009,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ int msgnum; int duration = 0; int sound_duration = 0; - int ausemacro = 0; - int ousemacro = 0; int ouseexten = 0; int greeting_only = 0; char tmpdur[16]; @@ -6524,9 +7031,10 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ const char *code; const char *alldtmf = "0123456789ABCD*#"; char flag[80]; + SCOPE_ENTER(3, "%s: %s\n", ast_channel_name(chan), ext); if (!tmp) { - return -1; + SCOPE_EXIT_RTN_VALUE(-1, "Failed to allocate memory for tmp\n"); } ast_str_set(&tmp, 0, "%s", ext); @@ -6558,10 +7066,10 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ ast_debug(3, "Before find_user\n"); memset(&svm, 0, sizeof(svm)); if (!(vmu = find_user(&svm, context, ext))) { - ast_log(AST_LOG_WARNING, "No entry in voicemail config file for '%s'\n", ext); pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED"); ast_free(tmp); - return res; + SCOPE_EXIT_LOG_RTN_VALUE(res, LOG_WARNING, + "%s: Exten: %s: No entry in voicemail config file for '%s'\n", ast_channel_name(chan), ext, ext); } /* If maxmsg is zero, act as a "greetings only" voicemail: Exit successfully without recording */ @@ -6586,22 +7094,27 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ } else if (ast_test_flag(options, OPT_UNAVAIL_GREETING)) { snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext); } + ast_trace(-1, "prefile: %s\n", prefile); /* Set the path to the tmpfile as VM_SPOOL_DIR/context/ext/temp and attempt to create the folder structure. */ snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext); + ast_trace(-1, "tempfile: %s\n", tempfile); if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) { - ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile); free_user(vmu); ast_free(tmp); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING, + "%s: Exten: %s: Failed to make directory (%s)\n", ast_channel_name(chan), ext, tempfile); } - RETRIEVE(tempfile, -1, vmu->mailbox, vmu->context); - if (ast_fileexists(tempfile, NULL, NULL) > 0) + SCOPE_CALL(-1, RETRIEVE, tempfile, -1, vmu->mailbox, vmu->context); + if (ast_fileexists(tempfile, NULL, NULL) > 0) { ast_copy_string(prefile, tempfile, sizeof(prefile)); + ast_trace(-1, "new prefile: %s\n", prefile); + } + + SCOPE_CALL(-1, DISPOSE, tempfile, -1); - DISPOSE(tempfile, -1); /* It's easier just to try to make it than to check for its existence */ #ifndef IMAP_STORAGE create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX"); @@ -6612,7 +7125,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ } #endif - /* Check current or macro-calling context for special extensions */ + /* Check current context for special extensions */ if (ast_test_flag(vmu, VM_OPERATOR)) { if (!ast_strlen_zero(vmu->exit)) { if (ast_exists_extension(chan, vmu->exit, "o", 1, @@ -6624,11 +7137,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1); ouseexten = 1; - } else if (!ast_strlen_zero(ast_channel_macrocontext(chan)) - && ast_exists_extension(chan, ast_channel_macrocontext(chan), "o", 1, - S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { - strncat(ecodes, "0", sizeof(ecodes) - strlen(ecodes) - 1); - ousemacro = 1; } } @@ -6640,11 +7148,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ } else if (ast_exists_extension(chan, ast_channel_context(chan), "a", 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1); - } else if (!ast_strlen_zero(ast_channel_macrocontext(chan)) - && ast_exists_extension(chan, ast_channel_macrocontext(chan), "a", 1, - S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { - strncat(ecodes, "*", sizeof(ecodes) - strlen(ecodes) - 1); - ausemacro = 1; } if (ast_test_flag(options, OPT_DTMFEXIT)) { @@ -6662,10 +7165,12 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ /* Play the beginning intro if desired */ if (!ast_strlen_zero(prefile)) { -#ifdef ODBC_STORAGE - int success = +#if defined(ODBC_STORAGE) + int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, ext, context); +#elif defined(IMAP_STORAGE) + SCOPE_CALL(-1, RETRIEVE, prefile, -1, ext, context); #endif - RETRIEVE(prefile, -1, ext, context); + if (ast_fileexists(prefile, NULL, NULL) > 0) { if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1) { /* We know we have a greeting at this point, so squelch the instructions @@ -6678,21 +7183,20 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ #ifdef ODBC_STORAGE if (success == -1) { /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */ - ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n"); - store_file(prefile, vmu->mailbox, vmu->context, -1); + ast_trace(-1, "Greeting '%s' not retrieved from database, but found in file storage. Inserting into database\n", prefile); + SCOPE_CALL(-1, odbc_store_message, prefile, vmu->mailbox, vmu->context, -1); } #endif } else { - ast_debug(1, "%s doesn't exist, doing what we can\n", prefile); + ast_trace(-1, "%s doesn't exist, doing what we can\n", prefile); res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes); } - DISPOSE(prefile, -1); + SCOPE_CALL(-1, DISPOSE, prefile, -1); if (res < 0) { - ast_debug(1, "Hang up during prefile playback\n"); free_user(vmu); pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED"); ast_free(tmp); - return -1; + SCOPE_EXIT_RTN_VALUE(-1, "Hang up during prefile playback\n"); } } if (res == '#') { @@ -6715,25 +7219,21 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ ast_channel_exten_set(chan, "a"); if (!ast_strlen_zero(vmu->exit)) { ast_channel_context_set(chan, vmu->exit); - } else if (ausemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) { - ast_channel_context_set(chan, ast_channel_macrocontext(chan)); } ast_channel_priority_set(chan, 0); free_user(vmu); pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT"); ast_free(tmp); - return 0; + SCOPE_EXIT_RTN_VALUE(0, "User escaped with '*'\n"); } /* Check for a '0' here */ if (ast_test_flag(vmu, VM_OPERATOR) && res == '0') { transfer: - if (ouseexten || ousemacro) { + if (ouseexten) { ast_channel_exten_set(chan, "o"); if (!ast_strlen_zero(vmu->exit)) { ast_channel_context_set(chan, vmu->exit); - } else if (ousemacro && !ast_strlen_zero(ast_channel_macrocontext(chan))) { - ast_channel_context_set(chan, ast_channel_macrocontext(chan)); } ast_play_and_wait(chan, "transfer"); ast_channel_priority_set(chan, 0); @@ -6741,7 +7241,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ } free_user(vmu); ast_free(tmp); - return OPERATOR_EXIT; + SCOPE_EXIT_RTN_VALUE(OPERATOR_EXIT, "User escaped with '0'\n"); } /* Allow all other digits to exit Voicemail and return to the dialplan */ @@ -6752,7 +7252,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ free_user(vmu); ast_free(tmp); pbx_builtin_setvar_helper(chan, "VMSTATUS", "USEREXIT"); - return res; + SCOPE_EXIT_RTN_VALUE(res, "User escaped back to dialplan '%c'\n", res); } if (greeting_only) { @@ -6766,7 +7266,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ free_user(vmu); pbx_builtin_setvar_helper(chan, "VMSTATUS", "FAILED"); ast_free(tmp); - return -1; + SCOPE_EXIT_RTN_VALUE(-1, "Other error '%d'\n", res); } /* The meat of recording the message... All the announcements and beeps have been played*/ if (ast_channel_state(chan) != AST_STATE_UP) { @@ -6812,7 +7312,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ goto leave_vm_out; } #else - if (count_messages(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) { + if (COUNT(vmu, dir) >= vmu->maxmsg - inprocess_count(vmu->mailbox, vmu->context, +1)) { res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan)); if (!res) res = ast_waitstream(chan, ""); @@ -6824,6 +7324,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ #endif snprintf(tmptxtfile, sizeof(tmptxtfile), "%s/XXXXXX", tmpdir); + ast_trace(-1, "Tempfile: %s\n", tmptxtfile); txtdes = mkstemp(tmptxtfile); chmod(tmptxtfile, VOICEMAIL_FILE_MODE & ~my_umask); if (txtdes < 0) { @@ -6857,7 +7358,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ ast_store_realtime("voicemail_data", "origmailbox", ext, "context", ast_channel_context(chan), - "macrocontext", ast_channel_macrocontext(chan), "exten", ast_channel_exten(chan), "priority", priority, "callerchan", ast_channel_name(chan), @@ -6885,7 +7385,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ "[message]\n" "origmailbox=%s\n" "context=%s\n" - "macrocontext=%s\n" "exten=%s\n" "rdnis=%s\n" "priority=%d\n" @@ -6897,7 +7396,6 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ "msg_id=%s\n", ext, ast_channel_context(chan), - ast_channel_macrocontext(chan), ast_channel_exten(chan), S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "unknown"), @@ -6907,6 +7405,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ date, (long) time(NULL), category ? category : "", msg_id); + ast_trace(-1, "Saving txt file mbox: %s msg_id: %s\n", ext, msg_id); } else { ast_log(AST_LOG_WARNING, "Error opening text file for output\n"); inprocess_count(vmu->mailbox, vmu->context, -1); @@ -6916,7 +7415,8 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ res = ast_streamfile(chan, "vm-mailboxfull", ast_channel_language(chan)); goto leave_vm_out; } - res = play_record_review(chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id, 0); + + res = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, NULL, tmptxtfile, vmu->maxsecs, fmt, 1, vmu, &duration, &sound_duration, NULL, options->record_gain, vms, flag, msg_id, 0); /* At this point, either we were instructed to make the message Urgent by arguments to VoiceMail or during the review process by the person @@ -6956,7 +7456,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ } } else { #ifndef IMAP_STORAGE - msgnum = last_message_index(vmu, dir) + 1; + msgnum = LAST_MSG_INDEX(dir) + 1; #endif make_file(fn, sizeof(fn), dir, msgnum); @@ -6968,7 +7468,12 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ #endif snprintf(txtfile, sizeof(txtfile), "%s.txt", fn); + + ast_trace(-1, "Renaming recordings '%s' -> fn '%s'\n", tmptxtfile, fn); + /* ast_filerename renames the recordings but not the txt file */ ast_filerename(tmptxtfile, fn, NULL); + + ast_trace(-1, "Renaming txt file '%s' -> fn '%s'\n", tmptxtfile, txtfile); rename(tmptxtfile, txtfile); inprocess_count(vmu->mailbox, vmu->context, -1); @@ -6986,7 +7491,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ * ODBC storage does the entire copy with SQL. */ if (ast_fileexists(fn, NULL, NULL) > 0) { - STORE(dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag, msg_id); + SCOPE_CALL(-1, STORE, dir, vmu->mailbox, vmu->context, msgnum, chan, vmu, fmt, duration, vms, flag, msg_id); } /* Are there to be more recipients of this message? */ @@ -7024,7 +7529,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ /* Disposal needs to happen after the optional move and copy */ if (ast_fileexists(fn, NULL, NULL)) { - DISPOSE(dir, msgnum); + SCOPE_CALL(-1, DISPOSE, dir, msgnum); } } } @@ -7062,7 +7567,7 @@ leave_vm_out: #endif ast_free(tmp); - return res; + SCOPE_EXIT_RTN_VALUE(res, "Done: '%d'\n", res); } #if !defined(IMAP_STORAGE) @@ -7078,7 +7583,7 @@ static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount) return ERROR_LOCK_PATH; } - for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) { + for (x = 0, dest = 0; dest != stopcount && x < MAXMSGLIMIT; x++) { make_file(sfn, sizeof(sfn), dir, x); if (EXISTS(dir, x, sfn, NULL)) { @@ -7162,41 +7667,47 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg char ddir[PATH_MAX]; const char *dbox = mbox(vmu, box); int x, i; + SCOPE_ENTER(3, "dir: %s msg: %d box: %d dbox: %s move? %d \n", dir, msg, box, dbox, move); + create_dirpath(ddir, sizeof(ddir), context, username, dbox); + ast_trace(-1, "ddir: %s\n", ddir); - if (vm_lock_path(ddir)) - return ERROR_LOCK_PATH; + if (vm_lock_path(ddir)) { + SCOPE_EXIT_RTN_VALUE(ERROR_LOCK_PATH, "Failed to lock path %s\n", ddir); + } - x = last_message_index(vmu, ddir) + 1; + x = LAST_MSG_INDEX(ddir) + 1; if (box == 10 && x >= vmu->maxdeletedmsg) { /* "Deleted" folder*/ + ast_trace(-1, "Deleting message %d\n", msg); x--; for (i = 1; i <= x; i++) { /* Push files down a "slot". The oldest file (msg0000) will be deleted. */ make_file(sfn, sizeof(sfn), ddir, i); make_file(dfn, sizeof(dfn), ddir, i - 1); if (EXISTS(ddir, i, sfn, NULL)) { - RENAME(ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn); + SCOPE_CALL(-1, RENAME, ddir, i, vmu->mailbox, vmu->context, ddir, i - 1, sfn, dfn); } else break; } } else { if (x >= vmu->maxmsg) { ast_unlock_path(ddir); - return ERROR_MAX_MSGS; + SCOPE_EXIT_RTN_VALUE(ERROR_MAX_MSGS, "Max messages reached\n"); } } make_file(sfn, sizeof(sfn), dir, msg); make_file(dfn, sizeof(dfn), ddir, x); if (strcmp(sfn, dfn)) { - COPY(dir, msg, ddir, x, username, context, sfn, dfn); + ast_trace(-1, "Copying message '%s' to '%s'\n", sfn, dfn); + SCOPE_CALL(-1, COPY, dir, msg, ddir, x, username, context, sfn, dfn); } ast_unlock_path(ddir); if (newmsg) { *newmsg = x; } - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Done\n"); #endif } @@ -7343,8 +7854,11 @@ static void adsi_begin(struct ast_channel *chan, int *useadsi) if (!ast_adsi_available(chan)) return; x = ast_adsi_load_session(chan, adsifdn, adsiver, 1); - if (x < 0) + if (x < 0) { + *useadsi = 0; + ast_channel_adsicpe_set(chan, AST_ADSI_UNAVAILABLE); return; + } if (!x) { if (adsi_load_vmail(chan, useadsi)) { ast_log(AST_LOG_WARNING, "Unable to upload voicemail scripts\n"); @@ -7837,8 +8351,9 @@ static int get_folder2(struct ast_channel *chan, char *fn, int start) * This is invoked from forward_message() when performing a forward operation (option 8 from main menu). * \return zero on success, -1 on error. */ -static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, - char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag) +static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, + int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, + struct vm_state *vms, char *flag) { int cmd = 0; int retries = 0, prepend_duration = 0, already_recorded = 0; @@ -7852,9 +8367,11 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, const char *msg_id = NULL; #endif const char *duration_str; + SCOPE_ENTER(3, "mbox: %s msgnum: %d curdir: %s", vmu->mailbox, curmsg, curdir); /* Must always populate duration correctly */ make_file(msgfile, sizeof(msgfile), curdir, curmsg); + ast_trace(-1, "msgfile: %s\n", msgfile); strcpy(textfile, msgfile); strcpy(backup, msgfile); strcpy(backup_textfile, msgfile); @@ -7891,8 +8408,11 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, #else /* prepend a message to the current message, update the metadata and return */ + ast_trace(-1, "Prepending to message %d\n", curmsg); make_file(msgfile, sizeof(msgfile), curdir, curmsg); + ast_trace(-1, "msgfile: %s\n", msgfile); + strcpy(textfile, msgfile); strncat(textfile, ".txt", sizeof(textfile) - 1); *duration = 0; @@ -7906,10 +8426,12 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, /* Back up the original file, so we can retry the prepend and restore it after forward. */ #ifndef IMAP_STORAGE if (already_recorded) { + ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile); ast_filecopy(backup, msgfile, NULL); copy(backup_textfile, textfile); } else { + ast_trace(-1, "Backing up '%s' to '%s'\n", backup, msgfile); ast_filecopy(msgfile, backup, NULL); copy(textfile, backup_textfile); } @@ -7919,7 +8441,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, if (record_gain) ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0); - cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, ast_play_and_prepend, chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence); if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */ ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */ @@ -7940,6 +8462,7 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char duration_buf[12]; *duration += prepend_duration; + ast_trace(-1, "Prepending duration: %d total duration: %ld\n", prepend_duration, *duration); msg_cat = ast_category_get(msg_cfg, "message", NULL); snprintf(duration_buf, sizeof(duration_buf), "%ld", *duration); if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) { @@ -7990,13 +8513,15 @@ static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, if (already_recorded && cmd == -1) { /* restore original message if prepention cancelled */ + ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile); ast_filerename(backup, msgfile, NULL); rename(backup_textfile, textfile); } - if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */ + if (cmd == 't' || cmd == 'S') { /* XXX entering this block with a value of 'S' is probably no longer possible. */ cmd = 0; - return cmd; + } + SCOPE_EXIT_RTN_VALUE(cmd, "Done. CMD: %d %c\n", cmd, cmd >= 32 && cmd < 127 ? cmd : '?'); } static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old) @@ -8182,11 +8707,16 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st #ifndef IMAP_STORAGE char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX]; #endif + SCOPE_ENTER(3, "%s: user: %s dir: %s msg: %d\n", ast_channel_name(chan), + vms->username, vms->curdir, vms->curmsg); + if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) { ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str)); } - if (vms == NULL) return -1; + if (vms == NULL) { + SCOPE_EXIT_RTN_VALUE(-1, "vms is NULL\n"); + } dir = vms->curdir; curmsg = vms->curmsg; @@ -8348,17 +8878,17 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st /* play name if available, else play extension number */ snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s); - RETRIEVE(fn, -1, s, receiver->context); + SCOPE_CALL(-1, RETRIEVE, fn, -1, s, receiver->context); if (ast_fileexists(fn, NULL, NULL) > 0) { res = ast_stream_and_wait(chan, fn, ecodes); if (res) { - DISPOSE(fn, -1); + SCOPE_CALL(-1, DISPOSE, fn, -1); return res; } } else { res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan)); } - DISPOSE(fn, -1); + SCOPE_CALL(-1, DISPOSE, fn, -1); s = strsep(&stringp, "*"); } @@ -8378,7 +8908,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st memset(&leave_options, 0, sizeof(leave_options)); leave_options.record_gain = record_gain; leave_options.beeptone = "beep"; - cmd = leave_voicemail(chan, mailbox, &leave_options); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, mailbox, &leave_options); } else { /* Forward VoiceMail */ long duration = 0; @@ -8392,7 +8922,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st #endif memcpy(&vmstmp, vms, sizeof(vmstmp)); - RETRIEVE(dir, curmsg, sender->mailbox, sender->context); + SCOPE_CALL(-1, RETRIEVE, dir, curmsg, sender->mailbox, sender->context); #ifdef IMAP_STORAGE make_file(filename, sizeof(filename), dir, curmsg); strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1); @@ -8403,7 +8933,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st } #endif - cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_forwardoptions, chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str); if (!cmd) { AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) { #ifdef IMAP_STORAGE @@ -8437,7 +8967,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, NULL, urgent_str, msg_id); #else - copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL); + copy_msg_result = SCOPE_CALL_WITH_INT_RESULT(-1, copy_message, chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL); #endif saved_messages++; AST_LIST_REMOVE_CURRENT(list); @@ -8477,7 +9007,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st } #endif } - DISPOSE(dir, curmsg); + SCOPE_CALL(-1, DISPOSE, dir, curmsg); #ifndef IMAP_STORAGE if (cmd) { /* assuming hangup, cleanup backup file */ make_file(msgfile, sizeof(msgfile), dir, curmsg); @@ -8495,7 +9025,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st inprocess_count(vmtmp->mailbox, vmtmp->context, -1); free_user(vmtmp); } - return res ? res : cmd; + SCOPE_EXIT_RTN_VALUE(res ? res : cmd, "Done. res: %d cmd: %d\n", res, cmd); } static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file) @@ -8739,6 +9269,8 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc const char *origtime, *context, *category, *duration, *flag; struct ast_config *msg_cfg; struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; + SCOPE_ENTER(3, "%s: user: %s dir: %s msg: %d\n", ast_channel_name(chan), + vms->username, vms->curdir, vms->curmsg); vms->starting = 0; make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); @@ -8750,7 +9282,7 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc } snprintf(filename, sizeof(filename), "%s.txt", vms->fn); - RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); + SCOPE_CALL(-1, RETRIEVE, vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); msg_cfg = ast_config_load(filename, config_flags); if (!valid_config(msg_cfg)) { ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename); @@ -8837,15 +9369,13 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc } if (!valid_config(msg_cfg)) { - ast_log(AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename); - return 0; + SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "No message attribute file?!! (%s)\n", filename); } if (!(origtime = ast_variable_retrieve(msg_cfg, "message", "origtime"))) { - ast_log(AST_LOG_WARNING, "No origtime?!\n"); - DISPOSE(vms->curdir, vms->curmsg); + SCOPE_CALL(-1, DISPOSE, vms->curdir, vms->curmsg); ast_config_destroy(msg_cfg); - return 0; + SCOPE_EXIT_LOG_RTN_VALUE(0, AST_LOG_WARNING, "No origtime?!\n"); } cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid")); @@ -8853,8 +9383,6 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc category = ast_variable_retrieve(msg_cfg, "message", "category"); context = ast_variable_retrieve(msg_cfg, "message", "context"); - if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */ - context = ast_variable_retrieve(msg_cfg, "message", "macrocontext"); if (!res) { res = play_message_category(chan, category); } @@ -8896,8 +9424,8 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc ast_test_suite_event_notify("USERPRESS", "Message: User pressed %c\r\nDTMF: %c", isprint(res) ? res : '?', isprint(res) ? res : '?'); } - DISPOSE(vms->curdir, vms->curmsg); - return res; + SCOPE_CALL(-1, DISPOSE, vms->curdir, vms->curmsg); + SCOPE_EXIT_RTN_VALUE(res, "Done: RC: %d\n", res); } #ifdef IMAP_STORAGE @@ -8991,6 +9519,8 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms) static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) { int count_msg, last_msg; + SCOPE_ENTER(3, "user: %s dir: %s msg: %d box %d\n", + vms->username, vms->curdir, vms->curmsg, box); ast_copy_string(vms->curbox, mbox(vmu, box), sizeof(vms->curbox)); @@ -9003,15 +9533,15 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vms->username, vms->curbox); /* traverses directory using readdir (or select query for ODBC) */ - count_msg = count_messages(vmu, vms->curdir); + count_msg = COUNT(vmu, vms->curdir); if (count_msg < 0) { - return count_msg; + SCOPE_EXIT_RTN_VALUE(count_msg, "msgs: %d\n", count_msg); } else { vms->lastmsg = count_msg - 1; } if (vm_allocate_dh(vms, vmu, count_msg)) { - return -1; + SCOPE_EXIT_RTN_VALUE(-1, "failed to allocate dh\n"); } /* @@ -9022,22 +9552,21 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) */ if (vm_lock_path(vms->curdir)) { - ast_log(AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir); - return ERROR_LOCK_PATH; + SCOPE_EXIT_LOG_RTN_VALUE(ERROR_LOCK_PATH, AST_LOG_ERROR, "Could not open mailbox %s: mailbox is locked\n", vms->curdir); } - /* for local storage, checks directory for messages up to maxmsg limit */ - last_msg = last_message_index(vmu, vms->curdir); + /* for local storage, checks directory for messages up to MAXMSGLIMIT */ + last_msg = LAST_MSG_INDEX(vms->curdir); ast_unlock_path(vms->curdir); if (last_msg < -1) { - return last_msg; + SCOPE_EXIT_RTN_VALUE(last_msg, "last msg: %d\n", last_msg); } else if (vms->lastmsg != last_msg) { ast_log(LOG_NOTICE, "Resequencing Mailbox: %s, expected %d but found %d message(s) in box with max threshold of %d.\n", vms->curdir, last_msg + 1, vms->lastmsg + 1, vmu->maxmsg); resequence_mailbox(vmu, vms->curdir, count_msg); } - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Done\n"); } #endif @@ -9050,8 +9579,11 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) int res = 0, nummsg; char fn2[PATH_MAX]; #endif + SCOPE_ENTER(3, "user: %s dir: %s msg: %d\n", + vms->username, vms->curdir, vms->curmsg); if (vms->lastmsg <= -1) { + ast_trace(-1, "No messages in mailbox\n"); goto done; } @@ -9059,11 +9591,11 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) #ifndef IMAP_STORAGE /* Get the deleted messages fixed */ if (vm_lock_path(vms->curdir)) { - return ERROR_LOCK_PATH; + SCOPE_EXIT_RTN_VALUE(ERROR_LOCK_PATH, "Could not open mailbox %s: mailbox is locked\n", vms->curdir); } /* update count as message may have arrived while we've got mailbox open */ - last_msg_idx = last_message_index(vmu, vms->curdir); + last_msg_idx = LAST_MSG_INDEX(vms->curdir); if (last_msg_idx != vms->lastmsg) { ast_log(AST_LOG_NOTICE, "%d messages received after mailbox opened.\n", last_msg_idx - vms->lastmsg); } @@ -9079,11 +9611,11 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) vms->curmsg++; make_file(fn2, sizeof(fn2), vms->curdir, vms->curmsg); if (strcmp(vms->fn, fn2)) { - RENAME(vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2); + SCOPE_CALL(-1, RENAME, vms->curdir, x, vmu->mailbox, vmu->context, vms->curdir, vms->curmsg, vms->fn, fn2); } } else if ((!strcasecmp(vms->curbox, "INBOX") || !strcasecmp(vms->curbox, "Urgent")) && vms->heard[x] && ast_test_flag(vmu, VM_MOVEHEARD) && !vms->deleted[x]) { /* Move to old folder before deleting */ - res = save_to_folder(vmu, vms, x, 1, NULL, 0); + res = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, vms, x, 1, NULL, 0); if (res == ERROR_LOCK_PATH || res == ERROR_MAX_MSGS) { /* If save failed do not delete the message */ ast_log(AST_LOG_WARNING, "Save failed. Not moving message: %s.\n", res == ERROR_LOCK_PATH ? "unable to lock path" : "destination folder full"); @@ -9093,8 +9625,9 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) } } else if (vms->deleted[x] && vmu->maxdeletedmsg) { /* Move to deleted folder */ - res = save_to_folder(vmu, vms, x, 10, NULL, 0); + res = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, vms, x, 10, NULL, 0); if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "Unable to lock path. Not moving message to deleted folder.\n"); /* If save failed do not delete the message */ vms->deleted[x] = 0; vms->heard[x] = 0; @@ -9104,8 +9637,9 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) /* If realtime storage enabled - we should explicitly delete this message, cause RENAME() will overwrite files, but will keep duplicate records in RT-storage */ make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); - if (EXISTS(vms->curdir, x, vms->fn, NULL)) { - DELETE(vms->curdir, x, vms->fn, vmu); + res = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, vms->curdir, x, vms->fn, NULL); + if (res) { + SCOPE_CALL(-1, DELETE, vms->curdir, x, vms->fn, vmu); } } } @@ -9114,8 +9648,9 @@ static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu) nummsg = x - 1; for (x = vms->curmsg + 1; x <= nummsg; x++) { make_file(vms->fn, sizeof(vms->fn), vms->curdir, x); - if (EXISTS(vms->curdir, x, vms->fn, NULL)) { - DELETE(vms->curdir, x, vms->fn, vmu); + res = SCOPE_CALL_WITH_INT_RESULT(-1, EXISTS, vms->curdir, x, vms->fn, NULL); + if (res) { + SCOPE_CALL(-1, DELETE, vms->curdir, x, vms->fn, vmu); } } ast_unlock_path(vms->curdir); @@ -9148,7 +9683,7 @@ done: ast_mutex_unlock(&vms->lock); #endif - return 0; + SCOPE_EXIT_RTN_VALUE(0, "Done\n"); } /* In Greek even though we CAN use a syntax like "friends messages" @@ -10692,6 +11227,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct char prefile[PATH_MAX] = ""; unsigned char buf[256]; int bytes = 0; + SCOPE_ENTER(3, "%s: %s entering mailbox options", ast_channel_name(chan), vms->username); ast_test_suite_event_notify("VMOPTIONS", "Message: entering mailbox options"); if (ast_adsi_available(chan)) { @@ -10708,15 +11244,15 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct switch (cmd) { case '1': /* Record your unavailable message */ snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username); - cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '2': /* Record your busy message */ snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username); - cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '3': /* Record greeting */ snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username); - cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '4': /* manage the temporary greeting */ cmd = vm_tempgreeting(chan, vmu, vms, fmtc, record_gain); @@ -10784,11 +11320,11 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct default: cmd = 0; snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username); - RETRIEVE(prefile, -1, vmu->mailbox, vmu->context); + SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, vmu->context); if (ast_fileexists(prefile, NULL, NULL)) { cmd = ast_play_and_wait(chan, "vm-tmpexists"); } - DISPOSE(prefile, -1); + SCOPE_CALL(-1, DISPOSE, prefile, -1); if (!cmd) { cmd = ast_play_and_wait(chan, "vm-options"); } @@ -10807,7 +11343,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct } if (cmd == 't') cmd = 0; - return cmd; + SCOPE_EXIT_RTN_VALUE(cmd, "Done\n"); } /*! @@ -11389,58 +11925,437 @@ play_msg_cleanup: res = -1; } - if (vmu && open) { - close_mailbox(&vms, vmu); + if (vmu && open) { + close_mailbox(&vms, vmu); + } + +#ifdef IMAP_STORAGE + if (vmu) { + vmstate_delete(&vms); + } +#endif + + free_user(vmu); + + return res; +} + +static int vm_playmsgexec(struct ast_channel *chan, const char *data) +{ + char *parse; + char *mailbox = NULL; + char *context = NULL; + int res; + + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(mailbox); + AST_APP_ARG(msg_id); + ); + + if (ast_channel_state(chan) != AST_STATE_UP) { + ast_debug(1, "Before ast_answer\n"); + ast_answer(chan); + } + + if (ast_strlen_zero(data)) { + return -1; + } + + parse = ast_strdupa(data); + AST_STANDARD_APP_ARGS(args, parse); + + if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) { + return -1; + } + + if ((context = strchr(args.mailbox, '@'))) { + *context++ = '\0'; + } + mailbox = args.mailbox; + + res = play_message_by_id(chan, mailbox, context, args.msg_id); + pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS"); + + return 0; +} + +static int show_mailbox_details(struct ast_cli_args *a) +{ +#define VMBOX_STRING_HEADER_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n" +#define VMBOX_STRING_DATA_FORMAT "%-32.32s %-32.32s %-16.16s %-16.16s %-16.16s %-16.16s\n" + + const char *mailbox = a->argv[3]; + const char *context = a->argv[4]; + struct vm_state vms; + struct ast_vm_user *vmu = NULL, vmus; + memset(&vmus, 0, sizeof(vmus)); + memset(&vms, 0, sizeof(vms)); + + if (!(vmu = find_user(&vmus, context, mailbox))) { + ast_cli(a->fd, "Can't find voicemail user %s@%s\n", mailbox, context); + return -1; + } + + ast_cli(a->fd, VMBOX_STRING_HEADER_FORMAT, "Full Name", "Email", "Pager", "Language", "Locale", "Time Zone"); + ast_cli(a->fd, VMBOX_STRING_DATA_FORMAT, vmu->fullname, vmu->email, vmu->pager, vmu->language, vmu->locale, vmu->zonetag); + + return 0; +} + +static int show_mailbox_snapshot(struct ast_cli_args *a) +{ +#define VM_STRING_HEADER_FORMAT "%-8.8s %-32.32s %-32.32s %-9.9s %-6.6s %-30.30s\n" + const char *mailbox = a->argv[3]; + const char *context = a->argv[4]; + struct ast_vm_mailbox_snapshot *mailbox_snapshot; + struct ast_vm_msg_snapshot *msg; + int i; + + /* Take a snapshot of the mailbox and walk through each folder's contents */ + mailbox_snapshot = ast_vm_mailbox_snapshot_create(mailbox, context, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0); + if (!mailbox_snapshot) { + ast_cli(a->fd, "Can't create snapshot for voicemail user %s@%s\n", mailbox, context); + return -1; + } + + ast_cli(a->fd, VM_STRING_HEADER_FORMAT, "Folder", "Caller ID", "Date", "Duration", "Flag", "ID"); + + for (i = 0; i < mailbox_snapshot->folders; i++) { + AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) { + ast_cli(a->fd, VM_STRING_HEADER_FORMAT, msg->folder_name, msg->callerid, msg->origdate, msg->duration, + msg->flag, msg->msg_id); + } + } + + ast_cli(a->fd, "%d Message%s Total\n", mailbox_snapshot->total_msg_num, ESS(mailbox_snapshot->total_msg_num)); + /* done, destroy. */ + mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot); + + return 0; +} + +static int show_messages_for_mailbox(struct ast_cli_args *a) +{ + if (show_mailbox_details(a)){ + return -1; + } + ast_cli(a->fd, "\n"); + return show_mailbox_snapshot(a); +} + +static int forward_message_from_mailbox(struct ast_cli_args *a) +{ + const char *from_mailbox = a->argv[2]; + const char *from_context = a->argv[3]; + const char *from_folder = a->argv[4]; + const char *id[] = { a->argv[5] }; + const char *to_mailbox = a->argv[6]; + const char *to_context = a->argv[7]; + const char *to_folder = a->argv[8]; + int ret = vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0); + if (ret) { + ast_cli(a->fd, "Error forwarding message %s from mailbox %s@%s %s to mailbox %s@%s %s\n", + id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder); + } else { + ast_cli(a->fd, "Forwarded message %s from mailbox %s@%s %s to mailbox %s@%s %s\n", + id[0], from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder); + } + return ret; +} + +static int move_message_from_mailbox(struct ast_cli_args *a) +{ + const char *mailbox = a->argv[2]; + const char *context = a->argv[3]; + const char *from_folder = a->argv[4]; + const char *id[] = { a->argv[5] }; + const char *to_folder = a->argv[6]; + int ret = vm_msg_move(mailbox, context, 1, from_folder, id, to_folder); + if (ret) { + ast_cli(a->fd, "Error moving message %s from mailbox %s@%s %s to %s\n", + id[0], mailbox, context, from_folder, to_folder); + } else { + ast_cli(a->fd, "Moved message %s from mailbox %s@%s %s to %s\n", + id[0], mailbox, context, from_folder, to_folder); + } + return ret; +} + +static int remove_message_from_mailbox(struct ast_cli_args *a) +{ + const char *mailbox = a->argv[2]; + const char *context = a->argv[3]; + const char *folder = a->argv[4]; + const char *id[] = { a->argv[5] }; + int ret = vm_msg_remove(mailbox, context, 1, folder, id); + if (ret) { + ast_cli(a->fd, "Error removing message %s from mailbox %s@%s %s\n", + id[0], mailbox, context, folder); + } else { + ast_cli(a->fd, "Removed message %s from mailbox %s@%s %s\n", + id[0], mailbox, context, folder); + } + return ret; +} + +static char *complete_voicemail_show_mailbox(struct ast_cli_args *a) +{ + const char *word = a->word; + int pos = a->pos; + int state = a->n; + int which = 0; + int wordlen; + struct ast_vm_user *vmu; + const char *context = "", *mailbox = ""; + char *ret = NULL; + + /* 0 - voicemail; 1 - show; 2 - mailbox; 3 - ; 4 - */ + if (pos == 3) { + wordlen = strlen(word); + AST_LIST_LOCK(&users); + AST_LIST_TRAVERSE(&users, vmu, list) { + if (!strncasecmp(word, vmu->mailbox , wordlen)) { + if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) { + ret = ast_strdup(vmu->mailbox); + AST_LIST_UNLOCK(&users); + return ret; + } + mailbox = vmu->mailbox; + } + } + AST_LIST_UNLOCK(&users); + } else if (pos == 4) { + /* Only display contexts that match the user in pos 3 */ + const char *box = a->argv[3]; + wordlen = strlen(word); + AST_LIST_LOCK(&users); + AST_LIST_TRAVERSE(&users, vmu, list) { + if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(box, vmu->mailbox)) { + if (context && strcmp(context, vmu->context) && ++which > state) { + ret = ast_strdup(vmu->context); + AST_LIST_UNLOCK(&users); + return ret; + } + context = vmu->context; + } + } + AST_LIST_UNLOCK(&users); + } + + return ret; +} + +static char *handle_voicemail_show_mailbox(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "voicemail show mailbox"; + e->usage = + "Usage: voicemail show mailbox \n" + " Show contents of mailbox @\n"; + return NULL; + case CLI_GENERATE: + return complete_voicemail_show_mailbox(a); + case CLI_HANDLER: + break; + } + + if (a->argc != 5) { + return CLI_SHOWUSAGE; + } + + if (show_messages_for_mailbox(a)) { + return CLI_FAILURE; + } + + return CLI_SUCCESS; +} + +/* Handles filling in data for one of the following three formats (based on maxpos = 5|6|8): + + maxpos = 5 + 0 - voicemail; 1 - forward; 2 - ; 3 - ; 4 - ; 5 - ; + maxpos = 6 + 0 - voicemail; 1 - forward; 2 - ; 3 - ; 4 - ; 5 - ; + 6 - ; + maxpos = 8 + 0 - voicemail; 1 - forward; 2 - ; 3 - ; 4 - ; 5 - ; + 6 - ; 7 - ; 8 - ; + + Passing in the maximum expected position 'maxpos' helps us fill in the missing entries in one function + instead of three by taking advantage of the overlap in the command sequence between forward, move and + remove as each of these use nearly the same syntax up until their maximum number of arguments. + The value of pos = 6 changes to be either or based on maxpos being 6 or 8. +*/ + +static char *complete_voicemail_move_message(struct ast_cli_args *a, int maxpos) +{ + const char *word = a->word; + int pos = a->pos; + int state = a->n; + int which = 0; + int wordlen; + struct ast_vm_user *vmu; + const char *context = "", *mailbox = "", *folder = "", *id = ""; + char *ret = NULL; + + if (pos > maxpos) { + /* If the passed in pos is above the max, return NULL to avoid 'over-filling' the cli */ + return NULL; + } + + /* if we are in pos 2 or pos 6 in 'forward' mode */ + if (pos == 2 || (pos == 6 && maxpos == 8)) { + /* find users */ + wordlen = strlen(word); + AST_LIST_LOCK(&users); + AST_LIST_TRAVERSE(&users, vmu, list) { + if (!strncasecmp(word, vmu->mailbox , wordlen)) { + if (mailbox && strcmp(mailbox, vmu->mailbox) && ++which > state) { + ret = ast_strdup(vmu->mailbox); + AST_LIST_UNLOCK(&users); + return ret; + } + mailbox = vmu->mailbox; + } + } + AST_LIST_UNLOCK(&users); + } else if (pos == 3 || pos == 7) { + /* find contexts that match the user */ + mailbox = (pos == 3) ? a->argv[2] : a->argv[6]; + wordlen = strlen(word); + AST_LIST_LOCK(&users); + AST_LIST_TRAVERSE(&users, vmu, list) { + if (!strncasecmp(word, vmu->context, wordlen) && !strcasecmp(mailbox, vmu->mailbox)) { + if (context && strcmp(context, vmu->context) && ++which > state) { + ret = ast_strdup(vmu->context); + AST_LIST_UNLOCK(&users); + return ret; + } + context = vmu->context; + } + } + AST_LIST_UNLOCK(&users); + } else if (pos == 4 || pos == 8 || (pos == 6 && maxpos == 6) ) { + int i; + /* Walk through the standard folders */ + wordlen = strlen(word); + for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) { + if (folder && !strncasecmp(word, mailbox_folders[i], wordlen) && ++which > state) { + return ast_strdup(mailbox_folders[i]); + } + folder = mailbox_folders[i]; + } + } else if (pos == 5) { + /* find messages in the folder */ + struct ast_vm_mailbox_snapshot *mailbox_snapshot; + struct ast_vm_msg_snapshot *msg; + mailbox = a->argv[2]; + context = a->argv[3]; + folder = a->argv[4]; + wordlen = strlen(word); + + /* Take a snapshot of the mailbox and snag the individual info */ + if ((mailbox_snapshot = ast_vm_mailbox_snapshot_create(mailbox, context, folder, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0))) { + int i; + /* we are only requesting the one folder, but we still need to know it's index */ + for (i = 0; i < ARRAY_LEN(mailbox_folders); i++) { + if (!strcasecmp(mailbox_folders[i], folder)) { + break; + } + } + AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) { + if (id && !strncasecmp(word, msg->msg_id, wordlen) && ++which > state) { + ret = ast_strdup(msg->msg_id); + break; + } + id = msg->msg_id; + } + /* done, destroy. */ + mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot); + } + } + + return ret; +} + +static char *handle_voicemail_forward_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "voicemail forward"; + e->usage = + "Usage: voicemail forward \n" + " Forward message in mailbox @ \n" + " to mailbox @ \n"; + return NULL; + case CLI_GENERATE: + return complete_voicemail_move_message(a, 8); + case CLI_HANDLER: + break; + } + + if (a->argc != 9) { + return CLI_SHOWUSAGE; } -#ifdef IMAP_STORAGE - if (vmu) { - vmstate_delete(&vms); + if (forward_message_from_mailbox(a)) { + return CLI_FAILURE; } -#endif - - free_user(vmu); - return res; + return CLI_SUCCESS; } -static int vm_playmsgexec(struct ast_channel *chan, const char *data) +static char *handle_voicemail_move_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { - char *parse; - char *mailbox = NULL; - char *context = NULL; - int res; - - AST_DECLARE_APP_ARGS(args, - AST_APP_ARG(mailbox); - AST_APP_ARG(msg_id); - ); + switch (cmd) { + case CLI_INIT: + e->command = "voicemail move"; + e->usage = + "Usage: voicemail move \n" + " Move message in mailbox & from to \n"; + return NULL; + case CLI_GENERATE: + return complete_voicemail_move_message(a, 6); + case CLI_HANDLER: + break; + } - if (ast_channel_state(chan) != AST_STATE_UP) { - ast_debug(1, "Before ast_answer\n"); - ast_answer(chan); + if (a->argc != 7) { + return CLI_SHOWUSAGE; } - if (ast_strlen_zero(data)) { - return -1; + if (move_message_from_mailbox(a)) { + return CLI_FAILURE; } - parse = ast_strdupa(data); - AST_STANDARD_APP_ARGS(args, parse); + return CLI_SUCCESS; +} - if (ast_strlen_zero(args.mailbox) || ast_strlen_zero(args.msg_id)) { - return -1; +static char *handle_voicemail_remove_message(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "voicemail remove"; + e->usage = + "Usage: voicemail remove \n" + " Remove message from in mailbox @\n"; + return NULL; + case CLI_GENERATE: + return complete_voicemail_move_message(a, 5); + case CLI_HANDLER: + break; } - if ((context = strchr(args.mailbox, '@'))) { - *context++ = '\0'; + if (a->argc != 6) { + return CLI_SHOWUSAGE; } - mailbox = args.mailbox; - res = play_message_by_id(chan, mailbox, context, args.msg_id); - pbx_builtin_setvar_helper(chan, "VOICEMAIL_PLAYBACKSTATUS", res ? "FAILED" : "SUCCESS"); + if (remove_message_from_mailbox(a)) { + return CLI_FAILURE; + } - return 0; + return CLI_SUCCESS; } static int vm_execmain(struct ast_channel *chan, const char *data) @@ -11469,6 +12384,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) #ifdef IMAP_STORAGE int deleted = 0; #endif + SCOPE_ENTER(3, "%s:\n", ast_channel_name(chan)); /* Add the vm_state to the active list and keep it active */ vms.lastmsg = -1; @@ -11492,14 +12408,14 @@ static int vm_execmain(struct ast_channel *chan, const char *data) AST_STANDARD_APP_ARGS(args, parse); if (args.argc == 2) { - if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) - return -1; + if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) { + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid option string '%s'\n", args.argv1); + } if (ast_test_flag(&flags, OPT_RECORDGAIN)) { int gain; if (!ast_strlen_zero(opts[OPT_ARG_RECORDGAIN])) { if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) { - ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]); } else { record_gain = (signed char) gain; } @@ -11570,10 +12486,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (!valid) res = vm_authenticate(chan, vms.username, sizeof(vms.username), &vmus, context, prefixstr, skipuser, maxlogins, 0); - ast_debug(1, "After vm_authenticate\n"); + ast_trace(-1, "vm_authenticate user: %s\n", vms.username); if (vms.username[0] == '*') { - ast_debug(1, "user pressed * in context '%s'\n", ast_channel_context(chan)); + ast_trace(-1, "user pressed * in context '%s'\n", ast_channel_context(chan)); /* user entered '*' */ if (!ast_goto_if_exists(chan, ast_channel_context(chan), "a", 1)) { @@ -11595,6 +12511,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) adsi_begin(chan, &useadsi); if (!valid) { + ast_trace(-1, "Invalid user\n"); goto out; } ast_test_suite_event_notify("AUTHENTICATED", "Message: vm_user authenticated"); @@ -11619,38 +12536,46 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } /* Retrieve urgent, old and new message counts */ - ast_debug(1, "Before open_mailbox\n"); - res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */ - if (res < 0) + ast_trace(-1, "Before open_mailbox\n"); + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */ + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } vms.oldmessages = vms.lastmsg + 1; - ast_debug(1, "Number of old messages: %d\n", vms.oldmessages); + ast_trace(-1, "Number of old messages: %d\n", vms.oldmessages); /* check INBOX */ - res = open_mailbox(&vms, vmu, NEW_FOLDER); - if (res < 0) + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } vms.newmessages = vms.lastmsg + 1; - ast_debug(1, "Number of new messages: %d\n", vms.newmessages); + ast_trace(-1, "Number of new messages: %d\n", vms.newmessages); /* Start in Urgent */ in_urgent = 1; - res = open_mailbox(&vms, vmu, 11); /*11 is the Urgent folder */ - if (res < 0) + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11); /*11 is the Urgent folder */ + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } vms.urgentmessages = vms.lastmsg + 1; - ast_debug(1, "Number of urgent messages: %d\n", vms.urgentmessages); + ast_trace(-1, "Number of urgent messages: %d\n", vms.urgentmessages); /* Select proper mailbox FIRST!! */ if (play_auto) { ast_test_suite_event_notify("AUTOPLAY", "Message: auto-playing messages"); if (vms.urgentmessages) { in_urgent = 1; - res = open_mailbox(&vms, vmu, 11); + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11); } else { in_urgent = 0; - res = open_mailbox(&vms, vmu, play_folder); + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, play_folder); } - if (res < 0) + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } /* If there are no new messages, inform the user and hangup */ if (vms.lastmsg == -1) { @@ -11662,7 +12587,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } else { if (!vms.newmessages && !vms.urgentmessages && vms.oldmessages) { /* If we only have old messages start here */ - res = open_mailbox(&vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */ + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, OLD_FOLDER); /* Count all messages, even Urgent */ in_urgent = 0; play_folder = 1; if (res < 0) @@ -11670,7 +12595,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } else if (!vms.urgentmessages && vms.newmessages) { /* If we have new messages but none are urgent */ in_urgent = 0; - res = open_mailbox(&vms, vmu, NEW_FOLDER); + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); if (res < 0) goto out; } @@ -11690,11 +12615,13 @@ static int vm_execmain(struct ast_channel *chan, const char *data) /* Timeout */ ast_test_suite_event_notify("TIMEOUT", "Message: response from user timed out"); res = 0; + ast_trace(-1, "Timeout\n"); goto out; } else if (cmd < 0) { /* Hangup */ ast_test_suite_event_notify("HANGUP", "Message: hangup detected"); res = -1; + ast_trace(-1, "Hangup\n"); goto out; } } @@ -11724,6 +12651,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) vms.starting = 1; while ((cmd > -1) && (cmd != 't') && (cmd != '#')) { /* Run main menu */ + ast_trace(-1, "Main menu: %d %c\n", cmd, (cmd >= 32 && cmd <= 126 ? cmd : ' ')); switch (cmd) { case '1': /* First message */ vms.curmsg = 0; @@ -11744,14 +12672,18 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = 0; } else if (cmd > 0) { cmd = cmd - '0'; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; + } /* If folder is not urgent, set in_urgent to zero! */ if (cmd != 11) in_urgent = 0; - res = open_mailbox(&vms, vmu, cmd); - if (res < 0) + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, cmd); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } play_folder = cmd; cmd = 0; } @@ -11776,6 +12708,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain); if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) { res = cmd; + ast_trace(-1, "advanced options: %d\n", cmd); goto out; } } else { @@ -11788,6 +12721,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) ast_verb(3, "Callback Requested\n"); if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) { cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain); + ast_trace(-1, "advanced options: %d\n", cmd); if (cmd == 9) { silentexit = 1; goto out; @@ -11805,6 +12739,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain); if (cmd == ERROR_LOCK_PATH) { res = cmd; + ast_trace(-1, "advanced options: %d\n", cmd); goto out; } } else { @@ -11817,6 +12752,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = dialout(chan, vmu, NULL, vmu->dialout); if (cmd == 9) { silentexit = 1; + ast_trace(-1, "dialout: %d\n", cmd); goto out; } } else { @@ -11827,9 +12763,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) case '5': /* Leave VoiceMail */ if (ast_test_flag(vmu, VM_SVMAIL)) { - cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 1, record_gain, 0); if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) { res = cmd; + ast_trace(-1, "forward message: %d\n", cmd); goto out; } } else { @@ -11884,7 +12821,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg - 1, vms.curmsg - 1); if (vms.curmsg > 0) { vms.curmsg--; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { /* Check if we were listening to new messages. If so, go to Urgent messages @@ -11893,12 +12830,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (in_urgent == 0 && vms.urgentmessages > 0) { /* Check for Urgent messages */ in_urgent = 1; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; - res = open_mailbox(&vms, vmu, 11); /* Open Urgent folder */ - if (res < 0) + } + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, 11); /* Open Urgent folder */ + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } ast_debug(1, "No more new messages, opened INBOX and got %d Urgent messages\n", vms.lastmsg + 1); vms.curmsg = vms.lastmsg; if (vms.lastmsg < 0) { @@ -11906,7 +12847,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = vms.lastmsg; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { cmd = ast_play_and_wait(chan, "vm-nomore"); } @@ -11916,7 +12857,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) ast_test_suite_event_notify("PREVMSG", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg + 1, vms.curmsg + 1); if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { if (in_urgent && vms.newmessages > 0) { /* Check if we were listening to urgent @@ -11924,12 +12865,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) * instead of saying "no more messages" */ in_urgent = 0; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; - res = open_mailbox(&vms, vmu, NEW_FOLDER); - if (res < 0) + } + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1); vms.curmsg = -1; if (vms.lastmsg < 0) { @@ -11937,7 +12882,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { cmd = ast_play_and_wait(chan, "vm-nomore"); } @@ -11974,10 +12919,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) { if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { /* Check if we were listening to urgent messages. If so, go to regular new messages @@ -11986,12 +12931,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (in_urgent == 1) { /* Check for new messages */ in_urgent = 0; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; - res = open_mailbox(&vms, vmu, NEW_FOLDER); - if (res < 0) + } + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1); vms.curmsg = -1; if (vms.lastmsg < 0) { @@ -12011,9 +12960,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) case '8': /* Forward the current message */ if (vms.lastmsg > -1) { - cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent); if (cmd == ERROR_LOCK_PATH) { res = cmd; + ast_trace(-1, "forward message: %d\n", res); goto out; } } else { @@ -12024,12 +12974,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (in_urgent == 1 && vms.newmessages > 0) { /* Check for new messages */ in_urgent = 0; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; - res = open_mailbox(&vms, vmu, NEW_FOLDER); - if (res < 0) + } + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1); vms.curmsg = -1; if (vms.lastmsg < 0) { @@ -12058,9 +13012,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) break; } else if (cmd > 0) { box = cmd = cmd - '0'; - cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, &vms, vms.curmsg, cmd, NULL, 0); if (cmd == ERROR_LOCK_PATH) { res = cmd; + ast_trace(-1, "save to folder: %d\n", res); goto out; #ifndef IMAP_STORAGE } else if (!cmd) { @@ -12089,10 +13044,10 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (ast_test_flag((&globalflags), VM_SKIPAFTERCMD)) { if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); } else { /* Check if we were listening to urgent messages. If so, go to regular new messages @@ -12101,12 +13056,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (in_urgent == 1 && vms.newmessages > 0) { /* Check for new messages */ in_urgent = 0; - res = close_mailbox(&vms, vmu); - if (res == ERROR_LOCK_PATH) + res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); + if (res == ERROR_LOCK_PATH) { + ast_trace(-1, "close mailbox: %d\n", res); goto out; - res = open_mailbox(&vms, vmu, NEW_FOLDER); - if (res < 0) + } + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); + if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; + } ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1); vms.curmsg = -1; if (vms.lastmsg < 0) { @@ -12150,12 +13109,13 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = 0; break; case '0': /* Mailbox options */ - cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_options,chan, vmu, &vms, vmfmts, record_gain); if (useadsi) adsi_status(chan, &vms); /* Reopen play_folder */ - res = open_mailbox(&vms, vmu, play_folder); + res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, play_folder); if (res < 0) { + ast_trace(-1, "open mailbox: %d\n", res); goto out; } vms.starting = 1; @@ -12190,8 +13150,9 @@ out: if (useadsi) ast_adsi_unload_session(chan); } - if (vmu) - close_mailbox(&vms, vmu); + if (vmu) { + SCOPE_CALL(-1, close_mailbox, &vms, vmu); + } if (valid) { int new = 0, old = 0, urgent = 0; snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context); @@ -12225,7 +13186,7 @@ out: #ifdef IMAP_STORAGE pthread_setspecific(ts_vmstate.key, NULL); #endif - return res; + SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res); } static int vm_exec(struct ast_channel *chan, const char *data) @@ -12239,6 +13200,7 @@ static int vm_exec(struct ast_channel *chan, const char *data) AST_APP_ARG(argv0); AST_APP_ARG(argv1); ); + SCOPE_ENTER(3, "%s\n", ast_channel_name(chan)); memset(&leave_options, 0, sizeof(leave_options)); @@ -12246,15 +13208,15 @@ static int vm_exec(struct ast_channel *chan, const char *data) tmp = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, tmp); if (args.argc == 2) { - if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) - return -1; + if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1)) { + SCOPE_EXIT_RTN_VALUE(-1, "parse options failed for '%s'\n", args.argv1); + } ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_SILENT_IF_GREET | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT); if (ast_test_flag(&flags, OPT_RECORDGAIN)) { int gain; if (sscanf(opts[OPT_ARG_RECORDGAIN], "%30d", &gain) != 1) { - ast_log(AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, AST_LOG_WARNING, "Invalid value '%s' provided for record gain option\n", opts[OPT_ARG_RECORDGAIN]); } else { leave_options.record_gain = (signed char) gain; } @@ -12272,10 +13234,12 @@ static int vm_exec(struct ast_channel *chan, const char *data) } else { char temp[256]; res = ast_app_getdata(chan, "vm-whichbox", temp, sizeof(temp) - 1, 0); - if (res < 0) - return res; - if (ast_strlen_zero(temp)) - return 0; + if (res < 0) { + SCOPE_EXIT_RTN_VALUE(res, "getdata failed. RC: %d", res); + } + if (ast_strlen_zero(temp)) { + SCOPE_EXIT_RTN_VALUE(0); + } args.argv0 = ast_strdupa(temp); } @@ -12287,7 +13251,7 @@ static int vm_exec(struct ast_channel *chan, const char *data) } } - res = leave_voicemail(chan, args.argv0, &leave_options); + res = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, args.argv0, &leave_options); if (res == 't') { ast_play_and_wait(chan, "vm-goodbye"); res = 0; @@ -12303,7 +13267,7 @@ static int vm_exec(struct ast_channel *chan, const char *data) res = 0; } - return res; + SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d", res); } static int add_message_id(struct ast_config *msg_cfg, char *dir, int msg, char *filename, char *id, size_t id_size, struct ast_vm_user *vmu, int folder) @@ -12443,7 +13407,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser) /* 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|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|" - "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|" + "sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|leaveurgent=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|" @@ -12519,6 +13483,10 @@ AST_TEST_DEFINE(test_voicemail_vmuser) ast_test_status_update(test, "Parse failure for review option\n"); res = 1; } + if (!ast_test_flag(vmu, VM_MARK_URGENT)) { + ast_test_status_update(test, "Parse failure for leaveurgent option\n"); + res = 1; + } if (!ast_test_flag(vmu, VM_TEMPGREETWARN)) { ast_test_status_update(test, "Parse failure for tempgreetwarm option\n"); res = 1; @@ -12625,6 +13593,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser) #endif free_user(vmu); + force_reload_config(); /* Restore original config */ return res ? AST_TEST_FAIL : AST_TEST_PASS; } #endif @@ -12801,19 +13770,25 @@ static char *complete_voicemail_show_users(const char *line, const char *word, i int wordlen; struct ast_vm_user *vmu; const char *context = ""; + char *ret; /* 0 - voicemail; 1 - show; 2 - users; 3 - for; 4 - */ if (pos > 4) return NULL; wordlen = strlen(word); + AST_LIST_LOCK(&users); AST_LIST_TRAVERSE(&users, vmu, list) { if (!strncasecmp(word, vmu->context, wordlen)) { - if (context && strcmp(context, vmu->context) && ++which > state) - return ast_strdup(vmu->context); + if (context && strcmp(context, vmu->context) && ++which > state) { + ret = ast_strdup(vmu->context); + AST_LIST_UNLOCK(&users); + return ret; + } /* ignore repeated contexts ? */ context = vmu->context; } } + AST_LIST_UNLOCK(&users); return NULL; } @@ -12997,6 +13972,10 @@ static struct ast_cli_entry cli_voicemail[] = { AST_CLI_DEFINE(handle_voicemail_show_zones, "List zone message formats"), AST_CLI_DEFINE(handle_voicemail_show_aliases, "List mailbox aliases"), AST_CLI_DEFINE(handle_voicemail_reload, "Reload voicemail configuration"), + AST_CLI_DEFINE(handle_voicemail_show_mailbox, "Display a mailbox's content details"), + AST_CLI_DEFINE(handle_voicemail_forward_message, "Forward message to another folder"), + AST_CLI_DEFINE(handle_voicemail_move_message, "Move message to another folder"), + AST_CLI_DEFINE(handle_voicemail_remove_message, "Remove message"), }; static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data) @@ -13239,6 +14218,7 @@ static int append_vmu_info_astman( "DeleteMessage: %s\r\n" "VolumeGain: %.2f\r\n" "CanReview: %s\r\n" + "CanMarkUrgent: %s\r\n" "CallOperator: %s\r\n" "MaxMessageCount: %d\r\n" "MaxMessageLength: %d\r\n" @@ -13276,6 +14256,7 @@ static int append_vmu_info_astman( ast_test_flag(vmu, VM_DELETE) ? "Yes" : "No", vmu->volgain, ast_test_flag(vmu, VM_REVIEW) ? "Yes" : "No", + ast_test_flag(vmu, VM_MARK_URGENT) ? "Yes" : "No", ast_test_flag(vmu, VM_OPERATOR) ? "Yes" : "No", vmu->maxmsg, vmu->maxsecs, @@ -13294,6 +14275,66 @@ static int append_vmu_info_astman( } + +/*! + * \brief Append vmbox info string into given astman with event_name. + * \return 0 if unable to append details, 1 otherwise. +*/ +static int append_vmbox_info_astman( + struct mansession *s, + const struct message *m, + struct ast_vm_user *vmu, + const char* event_name, + const char* actionid) +{ + struct ast_vm_mailbox_snapshot *mailbox_snapshot; + struct ast_vm_msg_snapshot *msg; + int nummessages = 0; + int i; + + /* Take a snapshot of the mailbox */ + mailbox_snapshot = ast_vm_mailbox_snapshot_create(vmu->mailbox, vmu->context, NULL, 0, AST_VM_SNAPSHOT_SORT_BY_ID, 0); + if (!mailbox_snapshot) { + ast_log(LOG_ERROR, "Could not append voicemail box info for box %s@%s.", + vmu->mailbox, vmu->context); + return 0; + } + + astman_send_listack(s, m, "Voicemail box detail will follow", "start"); + /* walk through each folder's contents and append info for each message */ + for (i = 0; i < mailbox_snapshot->folders; i++) { + AST_LIST_TRAVERSE(&((mailbox_snapshot)->snapshots[i]), msg, msg) { + astman_append(s, + "Event: %s\r\n" + "%s" + "Folder: %s\r\n" + "CallerID: %s\r\n" + "Date: %s\r\n" + "Duration: %s\r\n" + "Flag: %s\r\n" + "ID: %s\r\n" + "\r\n", + event_name, + actionid, + msg->folder_name, + msg->callerid, + msg->origdate, + msg->duration, + msg->flag, + msg->msg_id + ); + nummessages++; + } + } + + /* done, destroy. */ + mailbox_snapshot = ast_vm_mailbox_snapshot_destroy(mailbox_snapshot); + astman_send_list_complete_start(s, m, "VoicemailBoxDetailComplete", nummessages); + astman_send_list_complete_end(s); + + return 1; +} + static int manager_match_mailbox(struct ast_mwi_state *mwi_state, void *data) { const char *context = astman_get_header(data, "Context"); @@ -13419,6 +14460,163 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa return RESULT_SUCCESS; } +static int manager_get_mailbox_summary(struct mansession *s, const struct message *m) +{ + struct ast_vm_user *vmu = NULL; + const char *id = astman_get_header(m, "ActionID"); + char actionid[128]; + struct ast_vm_user svm; + + const char *context = astman_get_header(m, "Context"); + const char *mailbox = astman_get_header(m, "Mailbox"); + + if ((ast_strlen_zero(context) || ast_strlen_zero(mailbox))) { + astman_send_error(s, m, "Need 'Context' and 'Mailbox' parameters."); + return 0; + } + + actionid[0] = '\0'; + if (!ast_strlen_zero(id)) { + snprintf(actionid, sizeof(actionid), "ActionID: %s\r\n", id); + } + + /* find user */ + memset(&svm, 0, sizeof(svm)); + vmu = find_user(&svm, context, mailbox); + if (!vmu) { + /* could not find it */ + astman_send_ack(s, m, "There is no voicemail user matching the given user."); + return 0; + } + + /* Append the mailbox details */ + if (!append_vmbox_info_astman(s, m, vmu, "VoicemailBoxDetail", actionid)) { + astman_send_error(s, m, "Unable to get mailbox info for the given user."); + } + + free_user(vmu); + return 0; +} + +static int manager_voicemail_move(struct mansession *s, const struct message *m) +{ + const char *mailbox = astman_get_header(m, "Mailbox"); + const char *context = astman_get_header(m, "Context"); + const char *from_folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + const char *to_folder = astman_get_header(m, "ToFolder"); + + if (ast_strlen_zero(mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(from_folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + if (ast_strlen_zero(to_folder)) { + astman_send_error(s, m, "ToFolder not specified, required"); + return 0; + } + + if (vm_msg_move(mailbox, context, 1, from_folder, id, to_folder)) { + astman_send_ack(s, m, "Message move failed\n"); + } else { + astman_send_ack(s, m, "Message move successful\n"); + } + + return 0; +} + +static int manager_voicemail_remove(struct mansession *s, const struct message *m) +{ + const char *mailbox = astman_get_header(m, "Mailbox"); + const char *context = astman_get_header(m, "Context"); + const char *folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + + if (ast_strlen_zero(mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + + if (vm_msg_remove(mailbox, context, 1, folder, id)) { + astman_send_ack(s, m, "Message remove failed\n"); + } else { + astman_send_ack(s, m, "Message remove successful\n"); + } + + return 0; +} + +static int manager_voicemail_forward(struct mansession *s, const struct message *m) +{ + const char *from_mailbox = astman_get_header(m, "Mailbox"); + const char *from_context = astman_get_header(m, "Context"); + const char *from_folder = astman_get_header(m, "Folder"); + const char *id[] = { astman_get_header(m, "ID") }; + const char *to_mailbox = astman_get_header(m, "ToMailbox"); + const char *to_context = astman_get_header(m, "ToContext"); + const char *to_folder = astman_get_header(m, "ToFolder"); + + if (ast_strlen_zero(from_mailbox)) { + astman_send_error(s, m, "Mailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(from_context)) { + astman_send_error(s, m, "Context not specified, required"); + return 0; + } + if (ast_strlen_zero(from_folder)) { + astman_send_error(s, m, "Folder not specified, required"); + return 0; + } + if (ast_strlen_zero(id[0])) { + astman_send_error(s, m, "ID not specified, required"); + return 0; + } + if (ast_strlen_zero(to_mailbox)) { + astman_send_error(s, m, "ToMailbox not specified, required"); + return 0; + } + if (ast_strlen_zero(to_context)) { + astman_send_error(s, m, "ToContext not specified, required"); + return 0; + } + if (ast_strlen_zero(to_folder)) { + astman_send_error(s, m, "ToFolder not specified, required"); + return 0; + } + + if (vm_msg_forward(from_mailbox, from_context, from_folder, to_mailbox, to_context, to_folder, 1, id, 0)) { + astman_send_ack(s, m, "Message forward failed\n"); + } else { + astman_send_ack(s, m, "Message forward successful\n"); + } + + return 0; +} + /*! \brief Free the users structure. */ static void free_vm_users(void) { @@ -13488,10 +14686,10 @@ static const char *substitute_escapes(const char *value) return ast_str_buffer(str); } -static int load_config(int reload) +static int load_config_force(int reload, int force) { struct ast_config *cfg, *ucfg; - struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; + struct ast_flags config_flags = { reload && !force ? CONFIG_FLAG_FILEUNCHANGED : 0 }; int res; ast_unload_realtime("voicemail"); @@ -13529,6 +14727,11 @@ static int load_config(int reload) return res; } +static int load_config(int reload) +{ + return load_config_force(reload, 0); +} + #ifdef TEST_FRAMEWORK static int load_config_from_memory(int reload, struct ast_config *cfg, struct ast_config *ucfg) { @@ -13700,10 +14903,18 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con if ((val = ast_variable_retrieve(cfg, "general", "odbcstorage"))) { ast_copy_string(odbc_database, val, sizeof(odbc_database)); } + strcpy(odbc_table, "voicemessages"); if ((val = ast_variable_retrieve(cfg, "general", "odbctable"))) { ast_copy_string(odbc_table, val, sizeof(odbc_table)); } + odbc_table_len = strlen(odbc_table); + + ast_set2_flag((&globalflags), 0, VM_ODBC_AUDIO_ON_DISK); + if (!(val = ast_variable_retrieve(cfg, "general", "odbc_audio_on_disk"))) + val = "no"; + ast_set2_flag((&globalflags), ast_true(val), VM_ODBC_AUDIO_ON_DISK); + #endif /* Mail command */ strcpy(mailcmd, SENDMAIL); @@ -14023,6 +15234,14 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con } ast_set2_flag((&globalflags), ast_true(val), VM_REVIEW); + if (!(val = ast_variable_retrieve(cfg, "general", "leaveurgent"))){ + val = "yes"; + } else if (ast_false(val)) { + ast_debug(1, "VM leave urgent messages disabled globally\n"); + val = "no"; + } + ast_set2_flag((&globalflags), ast_true(val), VM_MARK_URGENT); + /* Temporary greeting reminder */ if (!(val = ast_variable_retrieve(cfg, "general", "tempgreetwarn"))) { ast_debug(1, "VM Temporary Greeting Reminder Option disabled globally\n"); @@ -14584,7 +15803,6 @@ AST_TEST_DEFINE(test_voicemail_msgcount) if (!(vmu = find_user(&svm, testcontext, testmailbox)) && !(vmu = find_or_create(testcontext, testmailbox))) { ast_test_status_update(test, "Cannot create vmu structure\n"); - ast_unreplace_sigchld(); #ifdef IMAP_STORAGE chan = ast_channel_unref(chan); #endif @@ -14606,7 +15824,6 @@ AST_TEST_DEFINE(test_voicemail_msgcount) if ((syserr = ast_safe_system(syscmd))) { ast_test_status_update(test, "Unable to create test voicemail: %s\n", syserr > 0 ? strerror(syserr) : "unable to fork()"); - ast_unreplace_sigchld(); #ifdef IMAP_STORAGE chan = ast_channel_unref(chan); #endif @@ -14695,6 +15912,7 @@ AST_TEST_DEFINE(test_voicemail_msgcount) } free_user(vmu); + force_reload_config(); /* Restore original config */ return res; } @@ -14805,6 +16023,7 @@ AST_TEST_DEFINE(test_voicemail_notify_endl) } fclose(file); free_user(vmu); + force_reload_config(); /* Restore original config */ return res; } @@ -14877,8 +16096,8 @@ AST_TEST_DEFINE(test_voicemail_load_config) #undef CHECK - /* restore config */ - load_config(1); /* this might say "Failed to load configuration file." */ + /* Forcibly restore the original config, to reinitialize after test */ + force_reload_config(); /* this might say "Failed to load configuration file." */ cleanup: unlink(config_filename); @@ -14944,6 +16163,11 @@ AST_TEST_DEFINE(test_voicemail_vm_info) populate_defaults(vmu); vmu->email = ast_strdup("vm-info-test@example.net"); + if (!vmu->email) { + ast_test_status_update(test, "Cannot create vmu email\n"); + chan = ast_channel_unref(chan); + return AST_TEST_FAIL; + } ast_copy_string(vmu->fullname, "Test Framework Mailbox", sizeof(vmu->fullname)); ast_copy_string(vmu->pager, "vm-info-pager-test@example.net", sizeof(vmu->pager)); ast_copy_string(vmu->language, "en", sizeof(vmu->language)); @@ -15013,6 +16237,10 @@ static int unload_module(void) res |= ast_manager_unregister("VoicemailUsersList"); res |= ast_manager_unregister("VoicemailUserStatus"); res |= ast_manager_unregister("VoicemailRefresh"); + res |= ast_manager_unregister("VoicemailBoxSummary"); + res |= ast_manager_unregister("VoicemailMove"); + res |= ast_manager_unregister("VoicemailRemove"); + res |= ast_manager_unregister("VoicemailForward"); #ifdef TEST_FRAMEWORK res |= AST_TEST_UNREGISTER(test_voicemail_vmsayname); res |= AST_TEST_UNREGISTER(test_voicemail_msgcount); @@ -15140,6 +16368,10 @@ static int load_module(void) res |= ast_manager_register_xml("VoicemailUsersList", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_list_voicemail_users); res |= ast_manager_register_xml("VoicemailUserStatus", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_status_voicemail_user); res |= ast_manager_register_xml("VoicemailRefresh", EVENT_FLAG_USER, manager_voicemail_refresh); + res |= ast_manager_register_xml("VoicemailBoxSummary", EVENT_FLAG_CALL | EVENT_FLAG_REPORTING, manager_get_mailbox_summary); + res |= ast_manager_register_xml("VoicemailMove", EVENT_FLAG_USER, manager_voicemail_move); + res |= ast_manager_register_xml("VoicemailRemove", EVENT_FLAG_USER, manager_voicemail_remove); + res |= ast_manager_register_xml("VoicemailForward", EVENT_FLAG_USER, manager_voicemail_forward); #ifdef TEST_FRAMEWORK res |= AST_TEST_REGISTER(test_voicemail_vmsayname); res |= AST_TEST_REGISTER(test_voicemail_msgcount); @@ -15288,8 +16520,6 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s cid = ast_strdupa(ast_variable_retrieve(msg_cfg, "message", "callerid")); context = ast_variable_retrieve(msg_cfg, "message", "context"); - if (!strncasecmp("macro", context, 5)) /* Macro names in contexts are useless for our needs */ - context = ast_variable_retrieve(msg_cfg, "message", "macrocontext"); switch (option) { case 3: /* Play message envelope */ if (!res) { @@ -15470,13 +16700,14 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re char *acceptdtmf = "#"; char *canceldtmf = ""; int canceleddtmf = 0; - + SCOPE_ENTER(3, "%s: rf: %s fmt: %s type: %s vmu: %s\n", + ast_channel_name(chan), recordfile, fmt, outsidecaller ? "msg" : "greeting", + vmu->mailbox); /* Note that urgent and private are for flagging messages as such in the future */ /* barf if no pointer passed to store duration in */ if (duration == NULL) { - ast_log(AST_LOG_WARNING, "Error play_record_review called without duration pointer\n"); - return -1; + SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING, "%s\n", "Error play_record_review called without duration pointer\n"); } if (!outsidecaller) @@ -15496,22 +16727,26 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re } else { /* Otherwise 1 is to save the existing message */ ast_verb(3, "Saving message as is\n"); - if (!outsidecaller) + if (!outsidecaller) { + ast_trace(-1, "Renaming greeting '%s' to '%s'\n", tempfile, recordfile); ast_filerename(tempfile, recordfile, NULL); + } if (!forwardintro) { ast_stream_and_wait(chan, "vm-msgsaved", ""); } if (!outsidecaller) { /* Saves to IMAP server only if imapgreeting=yes */ - STORE(recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id); - DISPOSE(recordfile, -1); + ast_trace(-1, "Saving greeting '%s'\n", recordfile); + SCOPE_CALL(-1, STORE, recordfile, vmu->mailbox, vmu->context, -1, chan, vmu, fmt, *duration, vms, flag, msg_id); + SCOPE_CALL(-1, DISPOSE, recordfile, -1); } cmd = 't'; - return res; + SCOPE_EXIT_RTN_VALUE(res, "Message saved to %s\n", recordfile); } case '2': /* Review */ ast_verb(3, "Reviewing the message\n"); + ast_trace(-1, "Reviewing '%s'\n", tempfile); cmd = ast_stream_and_wait(chan, tempfile, AST_DIGIT_ANY); break; case '3': @@ -15532,9 +16767,8 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re } if (cmd == -1) { /* User has hung up, no options to give */ - ast_debug(1, "User hung up before message could be rerecorded\n"); ast_filedelete(tempfile, NULL); - return cmd; + SCOPE_EXIT_RTN_VALUE(cmd, "User hung up before message could be rerecorded. Deleted '%s'\n", tempfile); } recorded = 1; /* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */ @@ -15542,6 +16776,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0); if (ast_test_flag(vmu, VM_OPERATOR)) canceldtmf = "0"; + ast_trace(-1, "Recording '%s'\n", tempfile); cmd = ast_play_and_record_full(chan, playfile, tempfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, unlockdir, acceptdtmf, canceldtmf, 0, AST_RECORD_IF_EXISTS_OVERWRITE); if (strchr(canceldtmf, cmd)) { /* need this flag here to distinguish between pressing '0' during message recording or after */ @@ -15555,7 +16790,8 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re /* user was recording a greeting and they hung up, so let's delete the recording. */ ast_filedelete(tempfile, NULL); } - return cmd; + SCOPE_EXIT_RTN_VALUE(cmd, "User hung up after recording. %s %s\n", + outsidecaller ? "Saved message " : "Deleted greeting \n", tempfile); } if (cmd == '0') { break; @@ -15584,7 +16820,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re } break; case '4': - if (outsidecaller) { /* only mark vm messages */ + if (outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) { /* only mark vm messages */ /* Mark Urgent */ if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) { ast_verb(3, "marking message as Urgent\n"); @@ -15631,10 +16867,12 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re break; } if (msg_exists || recorded) { + ast_trace(-1, "Reviewing '%s'\n", tempfile); cmd = ast_play_and_wait(chan, "vm-saveoper"); if (!cmd) cmd = ast_waitfordigit(chan, 3000); if (cmd == '1') { + ast_trace(-1, "Saving '%s' to '%s'\n", tempfile, recordfile); ast_filerename(tempfile, recordfile, NULL); ast_play_and_wait(chan, "vm-msgsaved"); cmd = '0'; @@ -15646,9 +16884,10 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re ast_play_and_wait(chan, "vm-msgsaved"); cmd = '0'; } else { + ast_trace(-1, "Deleting '%s'\n", tempfile); ast_play_and_wait(chan, "vm-deleted"); - DELETE(tempfile, -1, tempfile, vmu); - DISPOSE(tempfile, -1); + SCOPE_CALL(-1, DELETE, tempfile, -1, tempfile, vmu); + SCOPE_CALL(-1, DISPOSE, tempfile, -1); cmd = '0'; } } @@ -15657,11 +16896,12 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re /* If the caller is an outside caller and the review option is enabled or it's forward intro allow them to review the message, but let the owner of the box review their OGM's */ - if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro) - return cmd; + if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro) { + SCOPE_EXIT_RTN_VALUE(cmd, "Done. Outside caller, review not set, no forwardintro\n"); + } if (msg_exists) { cmd = ast_play_and_wait(chan, "vm-review"); - if (!cmd && outsidecaller) { + if (!cmd && outsidecaller && ast_test_flag(vmu, VM_MARK_URGENT)) { if ((flag && ast_strlen_zero(flag)) || (!ast_strlen_zero(flag) && strcmp(flag, "Urgent"))) { cmd = ast_play_and_wait(chan, "vm-review-urgent"); } else if (flag) { @@ -15695,13 +16935,14 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re } if (!outsidecaller && (cmd == -1 || cmd == 't')) { /* Hang up or timeout, so delete the recording. */ + ast_trace(-1, "Deleting '%s' on hangup or timeout\n", tempfile); ast_filedelete(tempfile, NULL); } if (cmd != 't' && outsidecaller) ast_play_and_wait(chan, "vm-goodbye"); - return cmd; + SCOPE_EXIT_RTN_VALUE(cmd, "Done\n"); } static struct ast_vm_msg_snapshot *vm_msg_snapshot_alloc(void) diff --git a/debian/patches/sipwise_define_module.patch b/debian/patches/sipwise_define_module.patch index ea50413..5e49b54 100644 --- a/debian/patches/sipwise_define_module.patch +++ b/debian/patches/sipwise_define_module.patch @@ -8,7 +8,7 @@ Subject: sipwise_define_module 2 files changed, 6 insertions(+) diff --git a/apps/app_playback.c b/apps/app_playback.c -index 56c2a86..b9caab5 100644 +index 6b93b03..613e8c8 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c @@ -29,6 +29,9 @@ @@ -22,7 +22,7 @@ index 56c2a86..b9caab5 100644 #include "asterisk/file.h" diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 1aca59b..69371b0 100644 +index 714e4d9..e7d0be2 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -46,6 +46,9 @@ diff --git a/debian/patches/sipwise_fix_compile_warnings.patch b/debian/patches/sipwise_fix_compile_warnings.patch index 0775e64..73b5c84 100644 --- a/debian/patches/sipwise_fix_compile_warnings.patch +++ b/debian/patches/sipwise_fix_compile_warnings.patch @@ -26,10 +26,10 @@ index 393aefc..9ee80e1 100644 all: _all diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 69371b0..8cc4c93 100644 +index e7d0be2..138645b 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -4800,7 +4800,7 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu +@@ -5289,7 +5289,7 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu } if ((origtime = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(origtime, "%30d", &inttime) == 1) { @@ -38,7 +38,7 @@ index 69371b0..8cc4c93 100644 struct ast_tm tm; ast_localtime(&tv, &tm, NULL); ast_strftime_locale(origdate, sizeof(origdate), emaildateformat, &tm, S_OR(vmu->locale, NULL)); -@@ -5201,7 +5201,7 @@ static void make_email_file(FILE *p, +@@ -5690,7 +5690,7 @@ static void make_email_file(FILE *p, /* You might be tempted to do origdate, except that a) it's in the wrong * format, and b) it's missing for IMAP recordings. */ if ((v = ast_variable_retrieve(msg_cfg, "message", "origtime")) && sscanf(v, "%30d", &inttime) == 1) { diff --git a/debian/patches/sipwise_vm_add_actions_wmi.patch b/debian/patches/sipwise_vm_add_actions_wmi.patch index b008c62..edcffd4 100644 --- a/debian/patches/sipwise_vm_add_actions_wmi.patch +++ b/debian/patches/sipwise_vm_add_actions_wmi.patch @@ -3,14 +3,14 @@ Date: Thu, 26 Sep 2024 01:07:31 +0200 Subject: sipwise_vm_add_actions_wmi --- - apps/app_voicemail.c | 296 +++++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 277 insertions(+), 19 deletions(-) + apps/app_voicemail.c | 297 +++++++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 276 insertions(+), 21 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 8f4f3af..dbf21ca 100644 +index 6823da2..080d378 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1043,6 +1043,52 @@ static int adsiver = 1; +@@ -1182,6 +1182,52 @@ static int adsiver = 1; static char emaildateformat[32] = "%A, %B %d, %Y at %r"; static char pagerdateformat[32] = "%A, %B %d, %Y at %r"; @@ -63,44 +63,53 @@ index 8f4f3af..dbf21ca 100644 /* Forward declarations - generic */ #ifdef ODBC_STORAGE static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, const char *context, const char *alias); -@@ -1065,8 +1111,9 @@ static void read_password_from_file(const char *secretfn, char *password, int pa +@@ -1204,9 +1250,10 @@ static void read_password_from_file(const char *secretfn, char *password, int pa static int write_password_to_file(const char *secretfn, const char *password); static const char *substitute_escapes(const char *value); static int message_range_and_existence_check(struct vm_state *vms, const char *msg_ids [], size_t num_msgs, int *msg_nums, struct ast_vm_user *vmu); -static void notify_new_state(struct ast_vm_user *vmu); +static void notify_new_state(struct ast_vm_user *vmu, vm_node *vm_actions); static int append_vmu_info_astman(struct mansession *s, struct ast_vm_user *vmu, const char* event_name, const char* actionid); + static int append_vmbox_info_astman(struct mansession *s, const struct message *m, struct ast_vm_user *vmu, const char* event_name, const char* actionid); +static void get_id_callid(char *dir, int msg_num, char *msg_id, char *callid); /*! -@@ -4451,9 +4498,11 @@ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailbox +@@ -4866,8 +4913,8 @@ static void odbc_delete_message(const char *sdir, int smsg) + * This method is used for the COPY macro when mailboxes are stored in an ODBC back end. + */ + #define COPY_SQL_FMT "INSERT INTO %s (dir, msgnum, msg_id, context, callerid, origtime, " \ +- "duration, recording, flag, mailboxuser, mailboxcontext) " \ +- "SELECT ?,?,msg_id,context,callerid,origtime,duration,recording,flag,?,? " \ ++ "duration, recording, flag, mailboxuser, mailboxcontext, call_id) " \ ++ "SELECT ?,?,msg_id,context,callerid,origtime,duration,recording,flag,?,?,? " \ + "FROM %s WHERE dir=? AND msgnum=?" + static void odbc_copy_message(char *sdir, int smsg, char *ddir, int dmsg, char *dmailboxuser, char *dmailboxcontext) + { +@@ -4875,9 +4922,11 @@ static void odbc_copy_message(char *sdir, int smsg, char *ddir, int dmsg, char * + char *sql = MAKE_SQL_PTRA2(COPY_SQL_FMT); char msgnums[20]; char msgnumd[20]; - char msg_id[MSG_ID_LEN]; + char mid[256] = ""; + char callid[256] = ""; struct odbc_obj *obj; -- char *argv[] = { ddir, msgnumd, msg_id, dmailboxuser, dmailboxcontext, sdir, msgnums }; -- struct generic_prepare_struct gps = { .sql = sql, .argc = 7, .argv = argv }; -+ char *argv[] = { ddir, msgnumd, msg_id, dmailboxuser, dmailboxcontext, callid, sdir, msgnums }; -+ struct generic_prepare_struct gps = { .sql = sql, .argc = 8, .argv = argv }; +- char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, sdir, msgnums }; +- struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv }; ++ char *argv[] = { ddir, msgnumd, dmailboxuser, dmailboxcontext, callid, sdir, msgnums }; ++ struct generic_prepare_struct gps = { .sql = sql, .argc = 7, .argv = argv }; + SCOPE_ENTER(3, "sdir: %s smsg: %d duser: %s dcontext: %s ddir: %s dmsg: %d\n", + sdir, smsg, dmailboxuser, dmailboxcontext, ddir, dmsg); - generate_msg_id(msg_id); - delete_file(ddir, dmsg); -@@ -4465,7 +4514,10 @@ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailbox +@@ -4890,7 +4939,7 @@ static void odbc_copy_message(char *sdir, int smsg, char *ddir, int dmsg, char * snprintf(msgnums, sizeof(msgnums), "%d", smsg); snprintf(msgnumd, sizeof(msgnumd), "%d", dmsg); -- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, msg_id, context, macrocontext, callerid, origtime, duration, recording, flag, mailboxuser, mailboxcontext) SELECT ?,?,?,context,macrocontext,callerid,origtime,duration,recording,flag,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table); -+ +- + get_id_callid(sdir, smsg, mid, callid); -+ -+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir, msgnum, msg_id, context, macrocontext, callerid, origtime, duration, recording, flag, mailboxuser, mailboxcontext, call_id) SELECT ?,?,?,context,macrocontext,callerid,origtime,duration,recording,flag,?,?,? FROM %s WHERE dir=? AND msgnum=?", odbc_table, odbc_table); stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s] (You probably don't have MySQL 4.1 or later installed)\n\n", sql); -@@ -6285,8 +6337,9 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) +@@ -6785,8 +6834,9 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) return res; } @@ -111,7 +120,7 @@ index 8f4f3af..dbf21ca 100644 char arguments[2048]; char date[256]; struct ast_tm tm; -@@ -6329,14 +6382,39 @@ static void run_externnotify(const char *context, const char *extension, const c +@@ -6829,14 +6879,39 @@ static void run_externnotify(const char *context, const char *extension, const c } else if (ast_strlen_zero(number) || !strcmp(extension, number)) { ast_log(AST_LOG_WARNING, "Missing user number to run externnotify on context '%s'\n", ext_context); } else { @@ -156,7 +165,7 @@ index 8f4f3af..dbf21ca 100644 } else { // original short notify + extension snprintf(arguments, sizeof(arguments), "%s %s %s %s %d %d %d &", externnotify, S_OR(context, "\"\""), -@@ -6422,6 +6500,9 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) +@@ -6921,6 +6996,9 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) const char *category = NULL; /* pointless for now */ char msg_id[MSG_ID_LEN]; @@ -166,7 +175,7 @@ index 8f4f3af..dbf21ca 100644 /* Start by checking to see if the file actually exists... */ if (!(ast_fileexists(recdata->recording_file, recdata->recording_ext, NULL))) { ast_log(LOG_ERROR, "File: %s not found.\n", recdata->recording_file); -@@ -6678,7 +6759,9 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) +@@ -7174,7 +7252,9 @@ static int msg_create_from_file(struct ast_vm_recording_data *recdata) if (send_email) { /* We tried and failed. */ ast_log(LOG_WARNING, "Failed to allocate dummy channel, email will not be sent\n"); } @@ -177,7 +186,7 @@ index 8f4f3af..dbf21ca 100644 } } -@@ -8168,6 +8251,74 @@ static void load_vmu_timezone(struct ast_vm_user *vmu) +@@ -8669,6 +8749,74 @@ static void load_vmu_timezone(struct ast_vm_user *vmu) return; } @@ -252,7 +261,7 @@ index 8f4f3af..dbf21ca 100644 /*! * \brief Sends email notification that a user has a new voicemail waiting for them. * \param chan -@@ -8191,6 +8342,9 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8692,6 +8840,9 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, struct timeval msg_time = ast_tvnow(); struct vm_zone *tz = get_vmu_timezone(vmu); @@ -262,7 +271,7 @@ index 8f4f3af..dbf21ca 100644 ast_channel_lock(chan); if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) { category = ast_strdupa(category); -@@ -8258,7 +8412,9 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8759,7 +8910,9 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs); @@ -273,17 +282,17 @@ index 8f4f3af..dbf21ca 100644 #ifdef IMAP_STORAGE vm_delete(fn); /* Delete the file, but not the IMAP message */ -@@ -11424,6 +11580,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) - #ifdef IMAP_STORAGE +@@ -12311,6 +12464,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) int deleted = 0; #endif + SCOPE_ENTER(3, "%s:\n", ast_channel_name(chan)); + int mt = -1; + vm_node messages[50]; + vm_node_create(messages, 50); /* Add the vm_state to the active list and keep it active */ vms.curmsg = -1; -@@ -11614,6 +11773,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12510,6 +12666,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (vms.lastmsg == -1) { in_urgent = 0; cmd = vm_browse_messages(chan, &vms, vmu); @@ -295,7 +304,7 @@ index 8f4f3af..dbf21ca 100644 res = 0; goto out; } -@@ -11689,6 +11853,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12588,6 +12749,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) case '5': /* Play current message */ ast_test_suite_event_notify("BROWSE", "Message: browsing message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg); cmd = vm_browse_messages(chan, &vms, vmu); @@ -307,10 +316,10 @@ index 8f4f3af..dbf21ca 100644 break; case '2': /* Change folders */ folder_change = 1; -@@ -11779,6 +11948,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12683,6 +12849,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (vms.curmsg > 0) { vms.curmsg--; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -319,10 +328,10 @@ index 8f4f3af..dbf21ca 100644 } else { /* Check if we were listening to new messages. If so, go to Urgent messages -@@ -11801,6 +11975,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12709,6 +12880,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = vms.lastmsg; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -331,10 +340,10 @@ index 8f4f3af..dbf21ca 100644 } else { cmd = ast_play_and_wait(chan, "vm-nomore"); } -@@ -11811,6 +11990,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12719,6 +12895,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -343,10 +352,10 @@ index 8f4f3af..dbf21ca 100644 } else { if (in_urgent && vms.newmessages > 0) { /* Check if we were listening to urgent -@@ -11832,6 +12016,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12744,6 +12925,11 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -355,7 +364,7 @@ index 8f4f3af..dbf21ca 100644 } else { cmd = ast_play_and_wait(chan, "vm-nomore"); } -@@ -11853,6 +12042,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12765,6 +12951,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) else if (play_folder == 1) vms.oldmessages--; cmd = ast_play_and_wait(chan, "vm-deleted"); @@ -365,7 +374,7 @@ index 8f4f3af..dbf21ca 100644 } else { if (play_folder == 0) { if (in_urgent) { -@@ -11864,14 +12056,27 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12776,14 +12965,27 @@ static int vm_execmain(struct ast_channel *chan, const char *data) else if (play_folder == 1) vms.oldmessages++; cmd = ast_play_and_wait(chan, "vm-undeleted"); @@ -376,7 +385,7 @@ index 8f4f3af..dbf21ca 100644 if (ast_test_flag(vmu, VM_SKIPAFTERCMD)) { if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -384,7 +393,7 @@ index 8f4f3af..dbf21ca 100644 + } } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -393,10 +402,10 @@ index 8f4f3af..dbf21ca 100644 } else { /* Check if we were listening to urgent messages. If so, go to regular new messages -@@ -11922,6 +12127,29 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12838,6 +13040,29 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } else if (cmd > 0) { box = cmd = cmd - '0'; - cmd = save_to_folder(vmu, &vms, vms.curmsg, cmd, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, save_to_folder, vmu, &vms, vms.curmsg, cmd, NULL, 0); + if (!cmd) { + switch (box) { + case 0: // INBOX @@ -422,11 +431,11 @@ index 8f4f3af..dbf21ca 100644 + } if (cmd == ERROR_LOCK_PATH) { res = cmd; - goto out; -@@ -11953,9 +12181,19 @@ static int vm_execmain(struct ast_channel *chan, const char *data) + ast_trace(-1, "save to folder: %d\n", res); +@@ -12870,9 +13095,19 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (vms.curmsg < vms.lastmsg) { vms.curmsg++; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -434,7 +443,7 @@ index 8f4f3af..dbf21ca 100644 + } } else if (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms.lastmsg > 0) { vms.curmsg = 0; - cmd = play_message(chan, vmu, &vms); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_message, chan, vmu, &vms); + if (!cmd) { + vm_node_insert(messages, 'r', "", ""); + mt = vm_node_find_avail(messages); @@ -443,7 +452,7 @@ index 8f4f3af..dbf21ca 100644 } else { /* Check if we were listening to urgent messages. If so, go to regular new messages -@@ -12072,7 +12310,7 @@ out: +@@ -12995,7 +13230,7 @@ out: int new = 0, old = 0, urgent = 0; snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context); /* Urgent flag not passwd to externnotify here */ @@ -452,7 +461,7 @@ index 8f4f3af..dbf21ca 100644 ast_app_inboxcount2(ext_context, &urgent, &new, &old); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old); } -@@ -15993,13 +16231,13 @@ done: +@@ -17196,13 +17431,13 @@ done: return res; } @@ -468,7 +477,7 @@ index 8f4f3af..dbf21ca 100644 ast_app_inboxcount2(ext_context, &urgent, &new, &old); queue_mwi_event(NULL, ext_context, urgent, new, old); } -@@ -16026,6 +16264,9 @@ static int vm_msg_forward(const char *from_mailbox, +@@ -17229,6 +17464,9 @@ static int vm_msg_forward(const char *from_mailbox, int i; int *msg_nums; @@ -478,7 +487,7 @@ index 8f4f3af..dbf21ca 100644 if (ast_strlen_zero(from_mailbox) || ast_strlen_zero(to_mailbox)) { ast_log(LOG_WARNING, "Cannot forward message because either the from or to mailbox was not specified\n"); return -1; -@@ -16139,7 +16380,9 @@ vm_forward_cleanup: +@@ -17342,7 +17580,9 @@ vm_forward_cleanup: #endif if (!res) { @@ -489,7 +498,7 @@ index 8f4f3af..dbf21ca 100644 } free_user(vmu); -@@ -16163,6 +16406,9 @@ static int vm_msg_move(const char *mailbox, +@@ -17366,6 +17606,9 @@ static int vm_msg_move(const char *mailbox, int i; int *old_msg_nums; @@ -499,7 +508,7 @@ index 8f4f3af..dbf21ca 100644 if (ast_strlen_zero(mailbox)) { ast_log(LOG_WARNING, "Cannot move message because no mailbox was specified\n"); return -1; -@@ -16244,7 +16490,9 @@ vm_move_cleanup: +@@ -17447,7 +17690,9 @@ vm_move_cleanup: #endif if (!res) { @@ -510,7 +519,7 @@ index 8f4f3af..dbf21ca 100644 } free_user(vmu); -@@ -16265,6 +16513,9 @@ static int vm_msg_remove(const char *mailbox, +@@ -17468,6 +17713,9 @@ static int vm_msg_remove(const char *mailbox, int i; int *msg_nums; @@ -520,7 +529,7 @@ index 8f4f3af..dbf21ca 100644 if (ast_strlen_zero(mailbox)) { ast_log(LOG_WARNING, "Cannot remove message because no mailbox was specified\n"); return -1; -@@ -16342,7 +16593,9 @@ vm_remove_cleanup: +@@ -17545,7 +17793,9 @@ vm_remove_cleanup: #endif if (!res) { @@ -531,7 +540,7 @@ index 8f4f3af..dbf21ca 100644 } free_user(vmu); -@@ -16367,6 +16620,9 @@ static int vm_msg_play(struct ast_channel *chan, +@@ -17570,6 +17820,9 @@ static int vm_msg_play(struct ast_channel *chan, int duration = 0; const char *value; @@ -541,7 +550,7 @@ index 8f4f3af..dbf21ca 100644 if (ast_strlen_zero(mailbox)) { ast_log(LOG_WARNING, "Cannot play message because no mailbox was specified\n"); return -1; -@@ -16456,7 +16712,9 @@ play2_msg_cleanup: +@@ -17659,7 +17912,9 @@ play2_msg_cleanup: #endif if (!res) { diff --git a/debian/patches/sipwise_vm_add_arabic_support.patch b/debian/patches/sipwise_vm_add_arabic_support.patch index ba64aad..c29c1d8 100644 --- a/debian/patches/sipwise_vm_add_arabic_support.patch +++ b/debian/patches/sipwise_vm_add_arabic_support.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_add_arabic_support 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 7c914b8..beda819 100644 +index bf46d37..da26b2b 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -8511,8 +8511,9 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc +@@ -9014,8 +9014,9 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); adsi_message(chan, vms); @@ -22,7 +22,7 @@ index 7c914b8..beda819 100644 } else { if (!vms->curmsg) { res = wait_file2(chan, vms, "vm-first"); /* "First" */ -@@ -8561,6 +8562,18 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc +@@ -9064,6 +9065,18 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc } if (!res) res = wait_file2(chan, vms, "vm-message"); @@ -41,7 +41,7 @@ index 7c914b8..beda819 100644 /* HEBREW syntax */ } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { if (!vms->curmsg) { -@@ -9003,6 +9016,8 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box) +@@ -9509,6 +9522,8 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box) return cmd ? cmd : ast_play_and_wait(chan, box); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { return vm_play_folder_name_gr(chan, box); @@ -50,7 +50,7 @@ index 7c914b8..beda819 100644 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* Hebrew syntax */ return ast_play_and_wait(chan, box); } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */ -@@ -9164,6 +9179,59 @@ static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, co +@@ -9670,6 +9685,59 @@ static int vm_intro_multilang(struct ast_channel *chan, struct vm_state *vms, co return res; } @@ -110,7 +110,7 @@ index 7c914b8..beda819 100644 /* Default Hebrew syntax */ static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms) { -@@ -10149,6 +10217,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm +@@ -10655,6 +10723,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm return vm_intro_fr(chan, vms); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */ return vm_intro_gr(chan, vms); @@ -119,7 +119,7 @@ index 7c914b8..beda819 100644 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW syntax */ return vm_intro_he(chan, vms); } else if (!strncasecmp(ast_channel_language(chan), "is", 2)) { /* ICELANDIC syntax */ -@@ -10745,6 +10815,23 @@ static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, +@@ -11252,6 +11322,23 @@ static int vm_browse_messages_gr(struct ast_channel *chan, struct vm_state *vms, return cmd; } @@ -143,7 +143,7 @@ index 7c914b8..beda819 100644 /* Hebrew Syntax */ static int vm_browse_messages_he(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu) { -@@ -10983,6 +11070,8 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st +@@ -11490,6 +11577,8 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st return vm_browse_messages_es(chan, vms, vmu); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK */ return vm_browse_messages_gr(chan, vms, vmu); @@ -152,7 +152,7 @@ index 7c914b8..beda819 100644 } else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* HEBREW */ return vm_browse_messages_he(chan, vms, vmu); } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */ -@@ -11938,6 +12027,8 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12860,6 +12949,8 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (folder_change && vms.lastmsg == -1) { if(!strcasecmp(ast_channel_language(chan), "ro")) { ast_play_and_wait(chan, "vm-dir-empty"); diff --git a/debian/patches/sipwise_vm_add_callid.patch b/debian/patches/sipwise_vm_add_callid.patch index 6343903..4b7b3f1 100644 --- a/debian/patches/sipwise_vm_add_callid.patch +++ b/debian/patches/sipwise_vm_add_callid.patch @@ -3,84 +3,282 @@ Date: Mon, 21 Feb 2022 14:17:23 +0100 Subject: sipwise_vm_add_callid --- - apps/app_voicemail.c | 22 ++++++++++++++++------ - 1 file changed, 16 insertions(+), 6 deletions(-) + apps/app_voicemail.c | 69 +++++++++++++++++++++++++++++----------------------- + 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 951a9cc..d61a30e 100644 +index 801b682..4ec7b83 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -858,7 +858,7 @@ static char odbc_database[80] = "asterisk"; - static char odbc_table[80] = "voicemessages"; - #define RETRIEVE(a,b,c,d) retrieve_file(a,b) - #define DISPOSE(a,b) remove_file(a,b) --#define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d) -+#define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d,e) - #define EXISTS(a,b,c,d) (message_exists(a,b)) - #define RENAME(a,b,c,d,e,f,g,h) (rename_file(a,b,c,d,e,f)) - #define COPY(a,b,c,d,e,f,g,h) (copy_file(a,b,c,d,e,f)) -@@ -4480,6 +4480,7 @@ struct insert_data { +@@ -993,9 +993,9 @@ static char odbc_table[80] = "voicemessages"; + size_t odbc_table_len = sizeof(odbc_table); + #define COUNT(a, b) odbc_count_messages(a,b) + #define LAST_MSG_INDEX(a) odbc_last_message_index(a) +-#define RETRIEVE(a,b,c,d) odbc_retrieve_message(a,b) ++#define RETRIEVE(a,b,c,d,e) odbc_retrieve_message(a,b,e) + #define DISPOSE(a,b) odbc_remove_files(a,b) +-#define STORE(a,b,c,d,e,f,g,h,i,j,k) odbc_store_message(a,b,c,d) ++#define STORE(a,b,c,d,e,f,g,h,i,j,k) odbc_store_message(a,b,c,d,e) + #define EXISTS(a,b,c,d) (odbc_message_exists(a,b)) + #define RENAME(a,b,c,d,e,f,g,h) (odbc_rename_message(a,b,c,d,e,f)) + #define COPY(a,b,c,d,e,f,g,h) (odbc_copy_message(a,b,c,d,e,f)) +@@ -1005,7 +1005,7 @@ size_t odbc_table_len = sizeof(odbc_table); + #ifdef IMAP_STORAGE + #define DISPOSE(a,b) (imap_remove_file(a,b)) + #define STORE(a,b,c,d,e,f,g,h,i,j,k) (imap_store_file(a,b,c,d,e,f,g,h,i,j,k)) +-#define RETRIEVE(a,b,c,d) imap_retrieve_file(a,b,c,d) ++#define RETRIEVE(a,b,c,d,e) imap_retrieve_file(a,b,c,d) + #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0) + #define RENAME(a,b,c,d,e,f,g,h) (rename_file(g,h)); + #define COPY(a,b,c,d,e,f,g,h) (copy_file(g,h)); +@@ -1014,7 +1014,7 @@ size_t odbc_table_len = sizeof(odbc_table); + #else + #define COUNT(a, b) count_messages(a,b) + #define LAST_MSG_INDEX(a) last_message_index(a) +-#define RETRIEVE(a,b,c,d) ++#define RETRIEVE(a,b,c,d,e) + #define DISPOSE(a,b) + #define STORE(a,b,c,d,e,f,g,h,i,j,k) + #define EXISTS(a,b,c,d) (ast_fileexists(c,NULL,d) > 0) +@@ -4327,7 +4327,7 @@ static void odbc_update_set_audmagic(char *dir, int msg_num) + SCOPE_EXIT_RTN("Done\n"); + } + +-static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum); ++static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum, struct ast_channel *chan); + + /*! + * \brief Retrieves a file from an ODBC data store. +@@ -4343,7 +4343,7 @@ static int odbc_store_message(const char *dir, const char *mailboxuser, const ch + * + * \return 0 on success, -1 on error. + */ +-static int odbc_retrieve_message(char *dir, int msgnum) ++static int odbc_retrieve_message(char *dir, int msgnum, struct ast_channel *chan) + { + int x = 0; + int res; +@@ -4552,7 +4552,7 @@ bail: + * into the database overwriting the AUDIO_ON_DISK_MAGIC + * magic number. + */ +- SCOPE_CALL(-1, odbc_store_message, dir, mailboxuser, mailboxcontext, msgnum); ++ SCOPE_CALL(-1, odbc_store_message, dir, mailboxuser, mailboxcontext, msgnum, chan); + } + } + +@@ -4912,14 +4912,15 @@ struct insert_data { const char *category; const char *flag; const char *msg_id; + const char *call_id; }; - static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) -@@ -4508,6 +4509,9 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) - SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (void *) data->msg_id, 0, NULL); + #define STORE_SQL_FMT_CAT "INSERT INTO %s (dir, msgnum, recording, context, callerid, " \ +- "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, category) " \ +- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)" ++ "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, callid, category) " \ ++ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)" + #define STORE_SQL_FMT "INSERT INTO %s (dir, msgnum, recording, context, callerid, "\ +- "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id) "\ +- "VALUES (?,?,?,?,?,?,?,?,?,?,?)" ++ "origtime, duration, mailboxuser, mailboxcontext, flag, msg_id, callid) "\ ++ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?)" + + static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) + { +@@ -4965,6 +4966,7 @@ static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) + SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->mailboxcontext), 0, (void *) data->mailboxcontext, 0, NULL); + SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->flag), 0, (void *) data->flag, 0, NULL); + SQLBindParameter(stmt, 11, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->msg_id), 0, (void *) data->msg_id, 0, NULL); ++ SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->call_id), 0, (void *) data->call_id, 0, NULL); if (!ast_strlen_zero(data->category)) { - SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (void *) data->category, 0, NULL); -+ SQLBindParameter(stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->call_id), 0, (void *) data->call_id, 0, NULL); -+ } else { -+ SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->call_id), 0, (void *) data->call_id, 0, NULL); - } - res = ast_odbc_execute_sql(obj, stmt, data->sql); - if (!SQL_SUCCEEDED(res)) { -@@ -4532,7 +4536,7 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) + insert_sql = MAKE_SQL_PTRA(STORE_SQL_FMT_CAT); + SQLBindParameter(stmt, 12, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (void *) data->category, 0, NULL); +@@ -4995,7 +4997,7 @@ static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) * * \return the zero on success -1 on error. */ --static int store_file(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum) -+static int store_file(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum, struct ast_channel *chan) +-static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum) ++static int odbc_store_message(const char *dir, const char *mailboxuser, const char *mailboxcontext, int msgnum, struct ast_channel *chan) { int res = 0; int fd = -1; -@@ -4547,8 +4551,9 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail +@@ -5009,8 +5011,9 @@ static int odbc_store_message(const char *dir, const char *mailboxuser, const ch char *c; struct ast_config *cfg = NULL; struct odbc_obj *obj; + const char *call_id; - struct insert_data idata = { .sql = sql, .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext, -- .context = "", .macrocontext = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "" }; -+ .context = "", .macrocontext = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "", call_id = "" }; + struct insert_data idata = { .msgnums = msgnums, .dir = dir, .mailboxuser = mailboxuser, .mailboxcontext = mailboxcontext, +- .context = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "" }; ++ .context = "", .callerid = "", .origtime = "", .duration = "", .category = "", .flag = "", .msg_id = "", call_id = "" }; struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; + SCOPE_ENTER(3, "dir: %s user: %s context: %s msgnum: %d msgtype: %s\n", + dir, mailboxuser, mailboxcontext, msgnum, msgnum < 0 ? "Greeting" : "Message"); +@@ -5082,6 +5085,7 @@ static int odbc_store_message(const char *dir, const char *mailboxuser, const ch + } + } - delete_file(dir, msgnum); -@@ -4621,10 +4626,15 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail - idata.data = fdm; - idata.datalen = idata.indlen = fdlen; ++ + if (fd < 0) { + ast_trace(-1, "Audio stored on disk. Not reading sound file '%s' but setting magic number.\n", full_fn); + idata.data = AUDIO_ON_DISK_MAGIC; +@@ -5104,6 +5108,11 @@ static int odbc_store_message(const char *dir, const char *mailboxuser, const ch + idata.datalen = idata.indlen = fdlen; + } + if ((call_id = pbx_builtin_getvar_helper(chan, "IDENTIFIER"))) { + if (!ast_strlen_zero(call_id)) + idata.call_id = ast_strdupa(call_id); + } + - if (!ast_strlen_zero(idata.category)) -- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); -+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category,call_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); - else -- snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); -+ snprintf(sql, sizeof(sql), "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,call_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", odbc_table); - if (ast_strlen_zero(idata.origtime)) { idata.origtime = "0"; -@@ -6857,7 +6867,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + } +@@ -6243,7 +6252,7 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, ch + return -1; + } + +- RETRIEVE(fn, -1, ext, context); ++ RETRIEVE(fn, -1, ext, context, chan); + if (ast_fileexists(fn, NULL, NULL) > 0) { + res = ast_stream_and_wait(chan, fn, ecodes); + if (res) { +@@ -7282,7 +7291,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING, + "%s: Exten: %s: Failed to make directory (%s)\n", ast_channel_name(chan), ext, tempfile); + } +- SCOPE_CALL(-1, RETRIEVE, tempfile, -1, vmu->mailbox, vmu->context); ++ SCOPE_CALL(-1, RETRIEVE, tempfile, -1, vmu->mailbox, vmu->context, chan); + if (ast_fileexists(tempfile, NULL, NULL) > 0) { + ast_copy_string(prefile, tempfile, sizeof(prefile)); + ast_trace(-1, "new prefile: %s\n", prefile); +@@ -7341,9 +7350,9 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + /* Play the beginning intro if desired */ + if (!ast_strlen_zero(prefile)) { + #if defined(ODBC_STORAGE) +- int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, vmu->mailbox, context); ++ int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, vmu->mailbox, context, chan); + #elif defined(IMAP_STORAGE) +- SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, context); ++ SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, context, chan); + #endif + + if (ast_fileexists(prefile, NULL, NULL) > 0) { +@@ -7359,7 +7368,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ if (success == -1) { /* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */ - ast_debug(1, "Greeting not retrieved from database, but found in file storage. Inserting into database\n"); -- store_file(prefile, vmu->mailbox, vmu->context, -1); -+ store_file(prefile, vmu->mailbox, vmu->context, -1, chan); + ast_trace(-1, "Greeting '%s' not retrieved from database, but found in file storage. Inserting into database\n", prefile); +- SCOPE_CALL(-1, odbc_store_message, prefile, vmu->mailbox, vmu->context, -1); ++ SCOPE_CALL(-1, odbc_store_message, prefile, vmu->mailbox, vmu->context, -1, chan); } #endif } else { +@@ -8713,7 +8722,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, + #endif + + if (attach_user_voicemail) +- RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context); ++ RETRIEVE(todir, msgnum, vmu->mailbox, vmu->context, chan); + + /* XXX possible imap issue, should category be NULL XXX */ + sendmail(myserveremail, vmu, msgnum, vmu->context, vmu->mailbox, mbox(vmu, 0), cidnum, cidname, fn, NULL, fmt, duration, attach_user_voicemail, chan, category, flag, msg_id); +@@ -8995,7 +9004,7 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc + } + + snprintf(filename, sizeof(filename), "%s.txt", vms->fn); +- SCOPE_CALL(-1, RETRIEVE, vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); ++ SCOPE_CALL(-1, RETRIEVE, vms->curdir, vms->curmsg, vmu->mailbox, vmu->context, chan); + msg_cfg = ast_config_load(filename, config_flags); + if (!valid_config(msg_cfg)) { + ast_log(LOG_WARNING, "No message attribute file?!! (%s)\n", filename); +@@ -10599,7 +10608,7 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm + /* Notify the user that the temp greeting is set and give them the option to remove it */ + snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vmu->mailbox); + if (ast_test_flag(vmu, VM_TEMPGREETWARN)) { +- RETRIEVE(prefile, -1, vmu->mailbox, vmu->context); ++ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context, chan); + if (ast_fileexists(prefile, NULL, NULL) > 0) { + ast_play_and_wait(chan, "vm-tempgreetactive"); + } +@@ -11078,7 +11087,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct + default: + cmd = 0; + snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vmu->mailbox); +- SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, vmu->context); ++ SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, vmu->context, chan); + if (ast_fileexists(prefile, NULL, NULL)) { + cmd = ast_play_and_wait(chan, "vm-tmpexists"); + } +@@ -11143,7 +11152,7 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st + while ((cmd >= 0) && (cmd != 't')) { + if (cmd) + retries = 0; +- RETRIEVE(prefile, -1, vmu->mailbox, vmu->context); ++ RETRIEVE(prefile, -1, vmu->mailbox, vmu->context, chan); + if (ast_fileexists(prefile, NULL, NULL) <= 0) { + cmd = play_record_review(chan, "vm-rec-temp", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + if (cmd == -1) { +@@ -11661,7 +11670,7 @@ static int play_message_by_id_helper(struct ast_channel *chan, + wait_file(chan, vms, vms->introfn); + } + #endif +- RETRIEVE(vms->curdir,vms->curmsg,vmu->mailbox, vmu->context); ++ RETRIEVE(vms->curdir,vms->curmsg,vmu->mailbox, vmu->context, chan); + + if ((wait_file(chan, vms, vms->fn)) < 0) { + ast_log(AST_LOG_WARNING, "Playback of message %s failed\n", vms->fn); +@@ -15276,7 +15285,7 @@ static int sayname(struct ast_channel *chan, const char *mailbox, const char *co + char dir[PATH_MAX]; + snprintf(dir, sizeof(dir), "%s%s/%s/greet", VM_SPOOL_DIR, context, mailbox); + ast_debug(2, "About to try retrieving name file %s\n", dir); +- RETRIEVE(dir, -1, mailbox, context); ++ RETRIEVE(dir, -1, mailbox, context, chan); + if (ast_fileexists(dir, NULL, NULL)) { + res = ast_stream_and_wait(chan, dir, AST_DIGIT_ANY); + } +@@ -16248,7 +16257,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s + + /* Retrieve info from VM attribute file */ + snprintf(filename, sizeof(filename), "%s.txt", vms->fn); +- RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); ++ RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context, chan); + msg_cfg = ast_config_load(filename, config_flags); + DISPOSE(vms->curdir, vms->curmsg); + if (!valid_config(msg_cfg)) { +@@ -16777,7 +16786,7 @@ static int vm_msg_snapshot_create(struct ast_vm_user *vmu, + /* Find the msg */ + make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); + snprintf(filename, sizeof(filename), "%s.txt", vms->fn); +- RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); ++ RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context, NULL); + msg_cfg = ast_config_load(filename, config_flags); + if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) { + DISPOSE(vms->curdir, vms->curmsg); +@@ -17038,7 +17047,7 @@ static int message_range_and_existence_check(struct vm_state *vms, const char *m + + make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); + snprintf(filename, sizeof(filename), "%s.txt", vms->fn); +- RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context); ++ RETRIEVE(vms->curdir, vms->curmsg, vmu->mailbox, vmu->context, NULL); + msg_cfg = ast_config_load(filename, config_flags); + if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) { + DISPOSE(vms->curdir, vms->curmsg); +@@ -17177,7 +17186,7 @@ static int vm_msg_forward(const char *from_mailbox, + + make_file(from_vms.fn, sizeof(from_vms.fn), from_vms.curdir, cur_msg); + snprintf(filename, sizeof(filename), "%s.txt", from_vms.fn); +- RETRIEVE(from_vms.curdir, cur_msg, vmu->mailbox, vmu->context); ++ RETRIEVE(from_vms.curdir, cur_msg, vmu->mailbox, vmu->context, NULL); + msg_cfg = ast_config_load(filename, config_flags); + /* XXX This likely will not fail since we previously ensured that the + * message we are looking for exists. However, there still could be some +@@ -17489,7 +17498,7 @@ static int vm_msg_play(struct ast_channel *chan, + /* Find the msg */ + make_file(vms.fn, sizeof(vms.fn), vms.curdir, vms.curmsg); + snprintf(filename, sizeof(filename), "%s.txt", vms.fn); +- RETRIEVE(vms.curdir, vms.curmsg, vmu->mailbox, vmu->context); ++ RETRIEVE(vms.curdir, vms.curmsg, vmu->mailbox, vmu->context, chan); + + msg_cfg = ast_config_load(filename, config_flags); + if (!msg_cfg || msg_cfg == CONFIG_STATUS_FILEINVALID) { diff --git a/debian/patches/sipwise_vm_add_pcre_support.patch b/debian/patches/sipwise_vm_add_pcre_support.patch index ad02887..821d9ed 100644 --- a/debian/patches/sipwise_vm_add_pcre_support.patch +++ b/debian/patches/sipwise_vm_add_pcre_support.patch @@ -33,7 +33,7 @@ index 9ee80e1..69eccd0 100644 all: _all @echo " +-------- app_voicemail Build Complete --------+" diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index d863f12..7833ae1 100644 +index 7667ae1..e9d5ec3 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -112,6 +112,9 @@ @@ -46,7 +46,7 @@ index d863f12..7833ae1 100644 /*** DOCUMENTATION -@@ -942,6 +945,8 @@ static int maxlogins = 3; +@@ -1081,6 +1084,8 @@ static int maxlogins = 3; static int minpassword = MINPASSWORD; static int passwordlocation; static char aliasescontext[MAX_VM_CONTEXT_LEN]; @@ -55,7 +55,7 @@ index d863f12..7833ae1 100644 /*! Poll mailboxes for changes since there is something external to * app_voicemail that may change them. */ -@@ -1177,6 +1182,134 @@ static int inprocess_count(const char *context, const char *mailbox, int delta) +@@ -1317,6 +1322,134 @@ static int inprocess_count(const char *context, const char *mailbox, int delta) static int __has_voicemail(const char *context, const char *mailbox, const char *folder, int shortcircuit); #endif @@ -190,7 +190,7 @@ index d863f12..7833ae1 100644 /*! * \brief Strips control and non 7-bit clean characters from input string. * -@@ -10797,6 +10930,10 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ +@@ -11317,6 +11450,10 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ int useadsi = 0, valid = 0, logretries = 0; char password[AST_MAX_EXTENSION], *passptr = NULL; struct ast_vm_user vmus, *vmu = NULL; @@ -201,7 +201,7 @@ index d863f12..7833ae1 100644 /* If ADSI is supported, setup login screen */ adsi_begin(chan, &useadsi); -@@ -10807,6 +10944,17 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ +@@ -11327,6 +11464,17 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ return -1; } @@ -219,7 +219,7 @@ index d863f12..7833ae1 100644 /* Authenticate them and get their mailbox/password */ while (!valid && (logretries < max_logins)) { -@@ -10836,6 +10984,18 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ +@@ -11356,6 +11504,18 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_ if (useadsi) adsi_password(chan); @@ -238,7 +238,7 @@ index d863f12..7833ae1 100644 if (!ast_strlen_zero(prefix)) { char fullusername[80]; -@@ -13171,6 +13331,8 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con +@@ -14349,6 +14509,8 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con char secretfn[PATH_MAX] = ""; long tps_queue_low; long tps_queue_high; @@ -247,9 +247,9 @@ index d863f12..7833ae1 100644 #ifdef IMAP_STORAGE ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder)); -@@ -13235,6 +13397,19 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con - ast_copy_string(odbc_table, val, sizeof(odbc_table)); - } +@@ -14421,6 +14583,19 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con + ast_set2_flag((&globalflags), ast_true(val), VM_ODBC_AUDIO_ON_DISK); + #endif + + /* sipwise sw_normalize_user_match/replace */ diff --git a/debian/patches/sipwise_vm_app_playback_timezone.patch b/debian/patches/sipwise_vm_app_playback_timezone.patch index 24fa866..7016cc0 100644 --- a/debian/patches/sipwise_vm_app_playback_timezone.patch +++ b/debian/patches/sipwise_vm_app_playback_timezone.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_app_playback_timezone 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/apps/app_playback.c b/apps/app_playback.c -index b9caab5..e7ad660 100644 +index 613e8c8..0a73b39 100644 --- a/apps/app_playback.c +++ b/apps/app_playback.c -@@ -237,6 +237,15 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth) +@@ -244,6 +244,15 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth) } AST_LIST_INSERT_HEAD(&head, n, entries); @@ -26,7 +26,7 @@ index b9caab5..e7ad660 100644 /* scan the body, one piece at a time */ while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */ char fn[128]; -@@ -250,6 +259,15 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth) +@@ -257,6 +266,15 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth) pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn)); ast_debug(2, "doing [%s]\n", fn); @@ -42,7 +42,7 @@ index b9caab5..e7ad660 100644 /* locate prefix and data, if any */ fmt = strchr(fn, ':'); if (!fmt || fmt == fn) { /* regular filename */ -@@ -333,10 +351,34 @@ static int say_date_generic(struct ast_channel *chan, time_t t, +@@ -340,10 +358,34 @@ static int say_date_generic(struct ast_channel *chan, time_t t, struct ast_tm tm; struct timeval when = { t, 0 }; say_args_t a = { chan, ints, lang, -1, -1 }; @@ -77,7 +77,7 @@ index b9caab5..e7ad660 100644 snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d", prefix, format, -@@ -348,7 +390,7 @@ static int say_date_generic(struct ast_channel *chan, time_t t, +@@ -355,7 +397,7 @@ static int say_date_generic(struct ast_channel *chan, time_t t, tm.tm_sec, tm.tm_wday, tm.tm_yday); diff --git a/debian/patches/sipwise_vm_ast_load_realtime_use_uuid.patch b/debian/patches/sipwise_vm_ast_load_realtime_use_uuid.patch index 470458b..facfe08 100644 --- a/debian/patches/sipwise_vm_ast_load_realtime_use_uuid.patch +++ b/debian/patches/sipwise_vm_ast_load_realtime_use_uuid.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_ast_load_realtime_use_uuid 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index d61a30e..beaff3a 100644 +index 4ec7b83..e5bdf95 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1772,7 +1772,7 @@ static int is_valid_dtmf(const char *key) +@@ -2044,7 +2044,7 @@ static int is_valid_dtmf(const char *key) * * \return The ast_vm_user structure for the user that was found. */ @@ -19,7 +19,7 @@ index d61a30e..beaff3a 100644 { struct ast_variable *var; struct ast_vm_user *retval; -@@ -1789,9 +1789,15 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha +@@ -2061,9 +2061,15 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha ast_copy_string(retval->mailbox, mailbox, sizeof(retval->mailbox)); } if (!context && ast_test_flag((&globalflags), VM_SEARCH)) { @@ -37,7 +37,7 @@ index d61a30e..beaff3a 100644 } if (var) { // ast_log (LOG_DEBUG,"call apply_options_full\n"); -@@ -1855,7 +1861,7 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex +@@ -2127,7 +2133,7 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex #ifdef ODBC_STORAGE vmu = find_user_realtime_by_alias(ivm, context, mailbox); #else @@ -46,7 +46,7 @@ index d61a30e..beaff3a 100644 #endif } if (!vmu && !ast_strlen_zero(aliasescontext)) { -@@ -4153,6 +4159,7 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, +@@ -4574,6 +4580,7 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, "where customer_id = ?"; struct generic_prepare_struct gps_uuid = { .sql = sql_uuid, .argc = 1, .argv = argv }; struct odbc_obj *obj = NULL; @@ -54,7 +54,7 @@ index d61a30e..beaff3a 100644 SQLHSTMT stmt = NULL; obj = ast_odbc_request_obj(odbc_database, 0); -@@ -4171,6 +4178,8 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, +@@ -4592,6 +4599,8 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, ast_log(LOG_NOTICE, "Failed to fetch mailbox for uuid '%s', falling back to alias search\n", alias); SQLFreeHandle (SQL_HANDLE_STMT, stmt); @@ -63,7 +63,7 @@ index d61a30e..beaff3a 100644 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps); if (!stmt) { ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); -@@ -4197,7 +4206,11 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, +@@ -4618,7 +4627,11 @@ static struct ast_vm_user *find_user_realtime_by_alias(struct ast_vm_user *ivm, ast_odbc_release_obj(obj); ast_log(LOG_NOTICE, "Found mailbox '%s' for alias '%s'\n", mailbox, alias); diff --git a/debian/patches/sipwise_vm_change_password_use_customer_id.patch b/debian/patches/sipwise_vm_change_password_use_customer_id.patch index 843ceb5..7c8c014 100644 --- a/debian/patches/sipwise_vm_change_password_use_customer_id.patch +++ b/debian/patches/sipwise_vm_change_password_use_customer_id.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_change_password_use_customer_id 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index a73b16e..3142c99 100644 +index fe73841..fcb96d7 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1639,7 +1639,7 @@ static int change_password_realtime(struct ast_vm_user *vmu, const char *passwor +@@ -1911,7 +1911,7 @@ static int change_password_realtime(struct ast_vm_user *vmu, const char *passwor if (strlen(password) > 10) { ast_realtime_require_field("voicemail", "password", RQ_CHAR, strlen(password), SENTINEL); } diff --git a/debian/patches/sipwise_vm_envelope_behaviour.patch b/debian/patches/sipwise_vm_envelope_behaviour.patch index 65c5091..adb27a3 100644 --- a/debian/patches/sipwise_vm_envelope_behaviour.patch +++ b/debian/patches/sipwise_vm_envelope_behaviour.patch @@ -9,10 +9,10 @@ and currently ignored per user 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 5070326..14c3922 100644 +index 77d81df..8dcbc73 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1455,8 +1455,6 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v +@@ -1727,8 +1727,6 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v ast_set2_flag(vmu, ast_true(value), VM_MESSAGEWRAP); } else if (!strcasecmp(var, "operator")) { ast_set2_flag(vmu, ast_true(value), VM_OPERATOR); @@ -21,8 +21,8 @@ index 5070326..14c3922 100644 } else if (!strcasecmp(var, "moveheard")){ ast_set2_flag(vmu, ast_true(value), VM_MOVEHEARD); } else if (!strcasecmp(var, "sayduration")){ -@@ -15011,7 +15009,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s - context = ast_variable_retrieve(msg_cfg, "message", "macrocontext"); +@@ -16216,7 +16214,7 @@ static int advanced_options(struct ast_channel *chan, struct ast_vm_user *vmu, s + context = ast_variable_retrieve(msg_cfg, "message", "context"); switch (option) { case 3: /* Play message envelope */ - if (!res) { diff --git a/debian/patches/sipwise_vm_ext_timezone.patch b/debian/patches/sipwise_vm_ext_timezone.patch index 2a0ea1a..b9f18e6 100644 --- a/debian/patches/sipwise_vm_ext_timezone.patch +++ b/debian/patches/sipwise_vm_ext_timezone.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_ext_timezone 1 file changed, 67 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index f26bbfa..951a9cc 100644 +index 72aa606..801b682 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -948,6 +948,8 @@ static int passwordlocation; +@@ -1087,6 +1087,8 @@ static int passwordlocation; static char aliasescontext[MAX_VM_CONTEXT_LEN]; static char sw_normalize_user_match[256]; static char sw_normalize_user_replace[256]; @@ -19,7 +19,7 @@ index f26bbfa..951a9cc 100644 /*! Poll mailboxes for changes since there is something external to * app_voicemail that may change them. */ -@@ -1092,6 +1094,7 @@ static int vm_msg_remove(const char *mailbox, const char *context, size_t num_ms +@@ -1232,6 +1234,7 @@ static int vm_msg_remove(const char *mailbox, const char *context, size_t num_ms static int vm_msg_play(struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb); static struct vm_zone *get_vmu_timezone(struct ast_vm_user *vmu); @@ -27,7 +27,7 @@ index f26bbfa..951a9cc 100644 #ifdef TEST_FRAMEWORK static int vm_test_destroy_user(const char *context, const char *mailbox); -@@ -1707,6 +1710,8 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable * +@@ -1979,6 +1982,8 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable * } else if (!strcasecmp(var->name, "mailbox")) { /* granig: but save number for announcement */ ast_copy_string(retval->dialed_num, var->value, sizeof(retval->dialed_num)); // ast_log (LOG_DEBUG,"setting dialed_num to '%s'\n", var->value); @@ -36,7 +36,7 @@ index f26bbfa..951a9cc 100644 #ifdef IMAP_STORAGE } else if (!strcasecmp(var->name, "imapuser")) { ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser)); -@@ -8076,6 +8081,58 @@ static struct vm_zone * get_vmu_timezone(struct ast_vm_user *vmu) +@@ -8587,6 +8592,58 @@ static struct vm_zone * get_vmu_timezone(struct ast_vm_user *vmu) return tz; } @@ -95,7 +95,7 @@ index f26bbfa..951a9cc 100644 /*! * \brief Sends email notification that a user has a new voicemail waiting for them. * \param chan -@@ -13324,6 +13381,9 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con +@@ -14499,6 +14556,9 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con long tps_queue_high; const char *ast_sw_normalize_user_match = NULL; const char *ast_sw_normalize_user_replace = NULL; @@ -105,7 +105,7 @@ index f26bbfa..951a9cc 100644 #ifdef IMAP_STORAGE ast_copy_string(imapparentfolder, "\0", sizeof(imapparentfolder)); -@@ -13401,6 +13461,13 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con +@@ -14584,6 +14644,13 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con sw_normalize_user_replace[0] = '\0'; } diff --git a/debian/patches/sipwise_vm_find_user_by_alias.patch b/debian/patches/sipwise_vm_find_user_by_alias.patch index 27eb829..c24d2df 100644 --- a/debian/patches/sipwise_vm_find_user_by_alias.patch +++ b/debian/patches/sipwise_vm_find_user_by_alias.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_find_user_by_alias 1 file changed, 71 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 446bb5d..d863f12 100644 +index 1ea9580..7667ae1 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1036,6 +1036,9 @@ static char emaildateformat[32] = "%A, %B %d, %Y at %r"; +@@ -1175,6 +1175,9 @@ static char emaildateformat[32] = "%A, %B %d, %Y at %r"; static char pagerdateformat[32] = "%A, %B %d, %Y at %r"; /* Forward declarations - generic */ @@ -20,7 +20,7 @@ index 446bb5d..d863f12 100644 static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box); static int close_mailbox(struct vm_state *vms, struct ast_vm_user *vmu); 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); -@@ -1709,7 +1712,12 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex +@@ -1981,7 +1984,12 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex AST_LIST_UNLOCK(&users); if (!vmu) { ast_log(LOG_DEBUG,"call find_user_realtime for '%s@%s'\n", mailbox, context); @@ -33,8 +33,8 @@ index 446bb5d..d863f12 100644 } if (!vmu && !ast_strlen_zero(aliasescontext)) { struct alias_mailbox_mapping *mapping; -@@ -3991,6 +3999,69 @@ bail: - return x - 1; +@@ -4412,6 +4420,69 @@ bail: + SCOPE_EXIT_RTN_VALUE(x - 1, "Done. msg_id: %s RC: %d\n", msg_id, x - 1); } +#ifdef ODBC_STORAGE @@ -102,4 +102,4 @@ index 446bb5d..d863f12 100644 + /*! * \brief Determines the highest message number in use for a given user and mailbox folder. - * \param vmu + * \param dir the folder the mailbox folder to look for messages. Used to construct the SQL where clause. diff --git a/debian/patches/sipwise_vm_fix_chan_usage.patch b/debian/patches/sipwise_vm_fix_chan_usage.patch index 4428896..d9b700e 100644 --- a/debian/patches/sipwise_vm_fix_chan_usage.patch +++ b/debian/patches/sipwise_vm_fix_chan_usage.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_fix_chan_usage 1 file changed, 2 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index a303308..0e7fb6a 100644 +index 193c9d3..5fdf7f0 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -14631,7 +14631,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount) +@@ -15848,7 +15848,9 @@ AST_TEST_DEFINE(test_voicemail_msgcount) break; } open_mailbox(&vms, vmu, folder2mbox[i]); diff --git a/debian/patches/sipwise_vm_fix_double_menu.patch b/debian/patches/sipwise_vm_fix_double_menu.patch index 7320d11..25f9757 100644 --- a/debian/patches/sipwise_vm_fix_double_menu.patch +++ b/debian/patches/sipwise_vm_fix_double_menu.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_fix_double_menu 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index dbf21ca..33ac414 100644 +index 080d378..a6cbec3 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -12236,16 +12236,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -13154,16 +13154,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) if (!cmd) cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete); break; diff --git a/debian/patches/sipwise_vm_fix_envelope_play.patch b/debian/patches/sipwise_vm_fix_envelope_play.patch index bbd94ad..82b813f 100644 --- a/debian/patches/sipwise_vm_fix_envelope_play.patch +++ b/debian/patches/sipwise_vm_fix_envelope_play.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_fix_envelope_play 1 file changed, 2 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 0e7fb6a..9105e1a 100644 +index 5fdf7f0..425f599 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -11809,6 +11809,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12743,6 +12743,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) break; case '3': /* Envelope */ if (vms.lastmsg > -1 && !vms.starting) { @@ -18,7 +18,7 @@ index 0e7fb6a..9105e1a 100644 cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 3, record_gain); if (cmd == ERROR_LOCK_PATH) { res = cmd; -@@ -11850,6 +11851,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12787,6 +12788,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) break; default: diff --git a/debian/patches/sipwise_vm_fix_odbc_retreive_file.patch b/debian/patches/sipwise_vm_fix_odbc_retreive_file.patch index 7aa5b5d..0350b80 100644 --- a/debian/patches/sipwise_vm_fix_odbc_retreive_file.patch +++ b/debian/patches/sipwise_vm_fix_odbc_retreive_file.patch @@ -7,11 +7,11 @@ Subject: sipwise_vm_fix_odbc_retreive_file 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 8cc4c93..a303308 100644 +index 138645b..193c9d3 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -3949,7 +3949,9 @@ static int retrieve_file(char *dir, int msgnum) - ast_debug(3, "Ignoring null category column in ODBC voicemail retrieve_file.\n"); +@@ -4350,7 +4350,9 @@ static int odbc_retrieve_message(char *dir, int msgnum) + ast_trace(-1, "Ignoring null category column in ODBC voicemail retrieve_file.\n"); continue; } else if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error! coltitle=%s\n[%s]\n\n", coltitle, sql); @@ -21,7 +21,7 @@ index 8cc4c93..a303308 100644 goto bail_with_handle; } if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir")) { -@@ -8893,7 +8895,9 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc +@@ -9421,7 +9423,9 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc } #endif if ((res = wait_file(chan, vms, vms->fn)) < 0) { diff --git a/debian/patches/sipwise_vm_fix_prev_message.patch b/debian/patches/sipwise_vm_fix_prev_message.patch index 24eede3..d97c9e3 100644 --- a/debian/patches/sipwise_vm_fix_prev_message.patch +++ b/debian/patches/sipwise_vm_fix_prev_message.patch @@ -7,11 +7,11 @@ Subject: sipwise_vm_fix_prev_message 1 file changed, 1 insertion(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index beda819..8f4f3af 100644 +index da26b2b..6823da2 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -11426,6 +11426,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) - #endif +@@ -12313,6 +12313,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) + SCOPE_ENTER(3, "%s:\n", ast_channel_name(chan)); /* Add the vm_state to the active list and keep it active */ + vms.curmsg = -1; diff --git a/debian/patches/sipwise_vm_hebrew_language_fixups.patch b/debian/patches/sipwise_vm_hebrew_language_fixups.patch index 768bdfd..b046fc4 100644 --- a/debian/patches/sipwise_vm_hebrew_language_fixups.patch +++ b/debian/patches/sipwise_vm_hebrew_language_fixups.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_hebrew_language_fixups 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index fe13968..7c914b8 100644 +index 21341bc..bf46d37 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -8510,10 +8510,15 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc +@@ -9013,10 +9013,15 @@ static int play_message(struct ast_channel *chan, struct ast_vm_user *vmu, struc vms->starting = 0; make_file(vms->fn, sizeof(vms->fn), vms->curdir, vms->curmsg); adsi_message(chan, vms); diff --git a/debian/patches/sipwise_vm_play_anonymous.patch b/debian/patches/sipwise_vm_play_anonymous.patch index 8afb47d..ca1456d 100644 --- a/debian/patches/sipwise_vm_play_anonymous.patch +++ b/debian/patches/sipwise_vm_play_anonymous.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_play_anonymous 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 3142c99..5070326 100644 +index fcb96d7..77d81df 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -8318,7 +8318,7 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, +@@ -8832,7 +8832,7 @@ static int play_message_callerid(struct ast_channel *chan, struct vm_state *vms, /* Strip off caller ID number from name */ ast_debug(1, "VM-CID: composite caller ID received: %s, context: %s\n", cid, context); ast_callerid_parse(cid, &name, &callerid); diff --git a/debian/patches/sipwise_vm_play_prompt_on_change_to_empty_folder.patch b/debian/patches/sipwise_vm_play_prompt_on_change_to_empty_folder.patch index a431058..ab5a042 100644 --- a/debian/patches/sipwise_vm_play_prompt_on_change_to_empty_folder.patch +++ b/debian/patches/sipwise_vm_play_prompt_on_change_to_empty_folder.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_play_prompt_on_change_to_empty_folder 1 file changed, 12 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 7833ae1..a73b16e 100644 +index e9d5ec3..fe73841 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -11250,6 +11250,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12149,6 +12149,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) signed char record_gain = 0; int play_auto = 0; int play_folder = 0; @@ -18,7 +18,7 @@ index 7833ae1..a73b16e 100644 int in_urgent = 0; int nodelete = 0; #ifdef IMAP_STORAGE -@@ -11519,6 +11520,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12431,6 +12432,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = vm_browse_messages(chan, &vms, vmu); break; case '2': /* Change folders */ @@ -26,7 +26,7 @@ index 7833ae1..a73b16e 100644 ast_test_suite_event_notify("CHANGEFOLDER", "Message: browsing to a different folder"); if (useadsi) adsi_folders(chan, 0, "Change to folder..."); -@@ -11852,6 +11854,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12787,6 +12789,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data) vms.starting = 1; break; default: /* Nothing */ diff --git a/debian/patches/sipwise_vm_pointers_malloc.patch b/debian/patches/sipwise_vm_pointers_malloc.patch index ebeb77e..4ce61b7 100644 --- a/debian/patches/sipwise_vm_pointers_malloc.patch +++ b/debian/patches/sipwise_vm_pointers_malloc.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_pointers_malloc 1 file changed, 2 insertions(+) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index c365407..fe13968 100644 +index d12f57d..21341bc 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -11333,6 +11333,8 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12220,6 +12220,8 @@ static int vm_execmain(struct ast_channel *chan, const char *data) /* Add the vm_state to the active list and keep it active */ vms.lastmsg = -1; diff --git a/debian/patches/sipwise_vm_romanian_syntax.patch b/debian/patches/sipwise_vm_romanian_syntax.patch index cb22ee0..24495c9 100644 --- a/debian/patches/sipwise_vm_romanian_syntax.patch +++ b/debian/patches/sipwise_vm_romanian_syntax.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_romanian_syntax 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index c6ad060..446bb5d 100644 +index a03fe25..1ea9580 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -667,6 +667,7 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con +@@ -801,6 +801,7 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con \arg \b es - Spanish \arg \b fr - French \arg \b it - Italian @@ -18,7 +18,7 @@ index c6ad060..446bb5d 100644 \arg \b nl - Dutch \arg \b pt - Portuguese \arg \b pt_BR - Portuguese (Brazil) -@@ -5631,6 +5632,17 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, ch +@@ -6123,6 +6124,17 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, ch } else { /* Dispose just in case */ DISPOSE(fn, -1); @@ -36,7 +36,7 @@ index c6ad060..446bb5d 100644 res = ast_say_digit_str(chan, dialed_num, ecodes, ast_channel_language(chan)); if (res) { ast_log(LOG_WARNING, "failed to stream/wait '%s'\n", dialed_num); -@@ -8053,6 +8065,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v +@@ -8567,6 +8579,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL); } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' q 'digits/at' 'digits/hours' k 'digits/e' M 'digits/minutes'", NULL); @@ -45,7 +45,7 @@ index c6ad060..446bb5d 100644 } else if (!strcasecmp(ast_channel_language(chan),"ja")) { /* Japanese syntax */ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "PHM q 'jp-ni' 'vm-received'", NULL); } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */ -@@ -8699,8 +8713,9 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box) +@@ -9218,8 +9232,9 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box) int cmd; if ( !strncasecmp(ast_channel_language(chan), "it", 2) || @@ -56,7 +56,7 @@ index c6ad060..446bb5d 100644 cmd = ast_play_and_wait(chan, "vm-messages"); /* "messages */ return cmd ? cmd : ast_play_and_wait(chan, box); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { -@@ -8972,6 +8987,52 @@ static int vm_intro_ja(struct ast_channel *chan,struct vm_state *vms) +@@ -9491,6 +9506,52 @@ static int vm_intro_ja(struct ast_channel *chan,struct vm_state *vms) return res; } /* Japanese */ @@ -109,7 +109,7 @@ index c6ad060..446bb5d 100644 /* Default English syntax */ static int vm_intro_en(struct ast_channel *chan, struct vm_state *vms) { -@@ -9811,6 +9872,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm +@@ -10330,6 +10391,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm return vm_intro_is(chan, vms); } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN syntax */ return vm_intro_it(chan, vms); @@ -118,7 +118,7 @@ index c6ad060..446bb5d 100644 } else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE syntax */ return vm_intro_ja(chan, vms); } else if (!strncasecmp(ast_channel_language(chan), "nl", 2)) { /* DUTCH syntax */ -@@ -10497,6 +10560,25 @@ static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, +@@ -11017,6 +11080,25 @@ static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, return cmd; } @@ -144,7 +144,7 @@ index c6ad060..446bb5d 100644 /*! * \brief Spanish syntax for 'You have N messages' greeting. * \param chan -@@ -10622,6 +10704,8 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st +@@ -11142,6 +11224,8 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st return vm_browse_messages_he(chan, vms, vmu); } else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */ return vm_browse_messages_it(chan, vms, vmu); diff --git a/debian/patches/sipwise_vm_sms_notify.patch b/debian/patches/sipwise_vm_sms_notify.patch index 26fcfd3..f3c4f81 100644 --- a/debian/patches/sipwise_vm_sms_notify.patch +++ b/debian/patches/sipwise_vm_sms_notify.patch @@ -3,14 +3,14 @@ Date: Mon, 21 Feb 2022 14:17:23 +0100 Subject: sipwise_vm_sms_notify --- - apps/app_voicemail.c | 173 ++++++++++++++------------------------------------- - 1 file changed, 48 insertions(+), 125 deletions(-) + apps/app_voicemail.c | 176 ++++++++++++++------------------------------------- + 1 file changed, 48 insertions(+), 128 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 14c3922..33dc99c 100644 +index 8dcbc73..e3182eb 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -934,6 +934,7 @@ static int silencethreshold = 128; +@@ -1073,6 +1073,7 @@ static int silencethreshold = 128; static char serveremail[80] = ASTERISK_USERNAME; static char mailcmd[160] = SENDMAIL; /* Configurable mail cmd */ static char externnotify[160]; @@ -18,8 +18,8 @@ index 14c3922..33dc99c 100644 static struct ast_smdi_interface *smdi_iface = NULL; static char vmfmts[80] = "wav"; static double volgain; -@@ -4969,6 +4970,15 @@ static int vm_delete(char *file) - return ast_filedelete(file, NULL); +@@ -5458,6 +5459,15 @@ static int vm_delete(char *file) + SCOPE_EXIT_RTN_VALUE(res, "Done. RC: %d\n", res); } +static void prep_pager_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, char *cidnum, char *dur, char *date) @@ -34,7 +34,7 @@ index 14c3922..33dc99c 100644 static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag) { char callerid[256]; -@@ -5646,150 +5656,56 @@ static int sendmail(char *srcemail, +@@ -6135,153 +6145,56 @@ static int sendmail(char *srcemail, return 0; } @@ -54,14 +54,14 @@ index 14c3922..33dc99c 100644 struct ast_tm tm; - FILE *p; - struct ast_str *str1 = ast_str_create(16), *str2 = ast_str_create(16); -+ struct ast_str *str1 = ast_str_create(16); - +- - if (!str1 || !str2) { - ast_free(str1); - ast_free(str2); - return -1; - } -- ++ struct ast_str *str1 = ast_str_create(16); + - if (cidnum) { - strip_control_and_high(cidnum, enc_cidnum, sizeof(enc_cidnum)); - } @@ -179,12 +179,15 @@ index 14c3922..33dc99c 100644 } - } else { - if (ast_strlen_zero(flag)) { -- fprintf(p, "Subject: New VM\n\n"); +- fprintf(p, "Subject: New VM" ENDL); - } else { -- fprintf(p, "Subject: New %s VM\n\n", flag); +- fprintf(p, "Subject: New %s VM" ENDL, flag); - } - } +- /* End of headers */ +- fputs(ENDL, p); +- - if (pagerbody) { - struct ast_channel *ast; - if ((ast = ast_dummy_channel_alloc())) { @@ -215,7 +218,7 @@ index 14c3922..33dc99c 100644 } /*! -@@ -8163,7 +8079,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8677,7 +8590,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, } if (!ast_strlen_zero(vmu->pager)) { @@ -224,7 +227,7 @@ index 14c3922..33dc99c 100644 } if (ast_test_flag(vmu, VM_DELETE)) -@@ -13590,6 +13506,13 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con +@@ -14776,6 +14689,13 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con externnotify[0] = '\0'; } diff --git a/debian/patches/sipwise_vm_store_message_add_diag_info.patch b/debian/patches/sipwise_vm_store_message_add_diag_info.patch index ef9e9e9..20d203c 100644 --- a/debian/patches/sipwise_vm_store_message_add_diag_info.patch +++ b/debian/patches/sipwise_vm_store_message_add_diag_info.patch @@ -3,45 +3,31 @@ Date: Mon, 21 Feb 2022 14:17:23 +0100 Subject: sipwise_vm_store_message_add_diag_info --- - apps/app_voicemail.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) + apps/app_voicemail.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index beaff3a..c365407 100644 +index e5bdf95..d12f57d 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -4502,6 +4502,10 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) +@@ -4942,6 +4942,9 @@ static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) + char *delete_sql; int res; SQLHSTMT stmt; - + SQLSMALLINT msg_len = 0; + SQLCHAR sql_state[6], message[256]; + SQLINTEGER native_error = 0; -+ - res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); - if (!SQL_SUCCEEDED(res)) { - ast_log(AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); -@@ -4528,7 +4532,8 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) + SCOPE_ENTER(3, "dir: %s msgnums: %s msg_id: %s\n", data->dir, data->msgnums, + data->msg_id); + +@@ -4988,8 +4991,8 @@ static SQLHSTMT odbc_insert_data_cb(struct odbc_obj *obj, void *vdata) } - res = ast_odbc_execute_sql(obj, stmt, data->sql); + res = ast_odbc_execute_sql(obj, stmt, insert_sql); if (!SQL_SUCCEEDED(res)) { -- ast_log(AST_LOG_WARNING, "SQL Direct Execute failed!\n"); +- ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n", insert_sql); +- ast_odbc_print_errors(SQL_HANDLE_STMT, stmt, "SQL Execute"); + res = SQLGetDiagRec(SQL_HANDLE_STMT, stmt, 1, sql_state, &native_error, message, sizeof(message), &msg_len); + ast_log(AST_LOG_WARNING, "SQL Direct Execute failed: code: %d msg: %s!\n", (int)native_error, message); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return NULL; + stmt = NULL; } -@@ -4661,6 +4666,13 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - } else { - ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); -+ /* -+ if (!ast_strlen_zero(idata.category)) { -+ ast_log(AST_LOG_WARNING, "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id,category) VALUES (%s,%s,,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)", odbc_table, idata.dir, idata.msgnums, idata.context, idata.macrocontext, idata.callerid, idata.origtime, idata.duration, idata.mailboxuser, idata.mailboxcontext, idata.flag, idata.msg_id, idata.category); -+ } else { -+ ast_log(AST_LOG_WARNING, "INSERT INTO %s (dir,msgnum,recording,context,macrocontext,callerid,origtime,duration,mailboxuser,mailboxcontext,flag,msg_id) VALUES (%s,%s,,%s,%s,%s,%s,%s,%s,%s,%s,%s)", odbc_table, idata.dir, idata.msgnums, idata.context, idata.macrocontext, idata.callerid, idata.origtime, idata.duration, idata.mailboxuser, idata.mailboxcontext, idata.flag, idata.msg_id); -+ } -+ */ - res = -1; - } - } while (0); diff --git a/debian/patches/sipwise_vm_uuid_mailbox.patch b/debian/patches/sipwise_vm_uuid_mailbox.patch index 92cd650..80b3e50 100644 --- a/debian/patches/sipwise_vm_uuid_mailbox.patch +++ b/debian/patches/sipwise_vm_uuid_mailbox.patch @@ -3,14 +3,14 @@ Date: Mon, 21 Feb 2022 14:17:23 +0100 Subject: sipwise_vm_uuid_mailbox --- - apps/app_voicemail.c | 756 +++++---------------------------------------------- - 1 file changed, 61 insertions(+), 695 deletions(-) + apps/app_voicemail.c | 783 ++++----------------------------------------------- + 1 file changed, 62 insertions(+), 721 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 9105e1a..c6ad060 100644 +index 425f599..a03fe25 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -760,7 +760,8 @@ and vm-Old are spelled plural, to make them sound more as folder name than an ad +@@ -894,7 +894,8 @@ and vm-Old are spelled plural, to make them sound more as folder name than an ad * Use ast_vm_user_destroy() to free one of these structures. */ struct ast_vm_user { char context[MAX_VM_CONTEXT_LEN];/*!< Voicemail context */ @@ -20,7 +20,7 @@ index 9105e1a..c6ad060 100644 char password[80]; /*!< Secret pin code, numbers only */ char fullname[80]; /*!< Full name, for directory app */ char *email; /*!< E-mail address */ -@@ -1562,6 +1563,12 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable * +@@ -1834,6 +1835,12 @@ static void apply_options_full(struct ast_vm_user *retval, struct ast_variable * } else if (!strcasecmp(var->name, "emailbody")) { ast_free(retval->emailbody); retval->emailbody = ast_strdup(substitute_escapes(var->value)); @@ -33,7 +33,7 @@ index 9105e1a..c6ad060 100644 #ifdef IMAP_STORAGE } else if (!strcasecmp(var->name, "imapuser")) { ast_copy_string(retval->imapuser, var->value, sizeof(retval->imapuser)); -@@ -1644,6 +1651,7 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha +@@ -1916,6 +1923,7 @@ static struct ast_vm_user *find_user_realtime(struct ast_vm_user *ivm, const cha var = ast_load_realtime("voicemail", "mailbox", mailbox, "context", context, SENTINEL); } if (var) { @@ -41,7 +41,7 @@ index 9105e1a..c6ad060 100644 apply_options_full(retval, var); ast_variables_destroy(var); } else { -@@ -1699,6 +1707,7 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex +@@ -1971,6 +1979,7 @@ static struct ast_vm_user *find_user(struct ast_vm_user *ivm, const char *contex } AST_LIST_UNLOCK(&users); if (!vmu) { @@ -49,7 +49,7 @@ index 9105e1a..c6ad060 100644 vmu = find_user_realtime(ivm, context, mailbox); } if (!vmu && !ast_strlen_zero(aliasescontext)) { -@@ -3048,7 +3057,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) +@@ -3336,7 +3345,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) return -1; } @@ -58,7 +58,7 @@ index 9105e1a..c6ad060 100644 /* Check Quota */ if (box == 0) { -@@ -4774,7 +4783,8 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu +@@ -5263,7 +5272,8 @@ static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu snprintf(num, sizeof(num), "%d", msgnum); pbx_builtin_setvar_helper(ast, "VM_MSGNUM", num); pbx_builtin_setvar_helper(ast, "VM_CONTEXT", context); @@ -68,7 +68,7 @@ index 9105e1a..c6ad060 100644 pbx_builtin_setvar_helper(ast, "VM_CALLERID", (!ast_strlen_zero(cidname) || !ast_strlen_zero(cidnum)) ? ast_callerid_merge(callerid, sizeof(callerid), cidname, cidnum, NULL) : "an unknown caller"); pbx_builtin_setvar_helper(ast, "VM_CIDNAME", (!ast_strlen_zero(cidname) ? cidname : "an unknown caller")); -@@ -5598,7 +5608,7 @@ static int get_date(char *s, int len) +@@ -6090,7 +6100,7 @@ static int get_date(char *s, int len) return ast_strftime(s, len, "%a %b %e %r UTC %Y", &tm); } @@ -77,7 +77,7 @@ index 9105e1a..c6ad060 100644 { int res; char fn[PATH_MAX]; -@@ -5621,12 +5631,11 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, in +@@ -6113,12 +6123,11 @@ static int invent_message(struct ast_channel *chan, char *context, char *ext, in } else { /* Dispose just in case */ DISPOSE(fn, -1); @@ -94,15 +94,15 @@ index 9105e1a..c6ad060 100644 } res = ast_stream_and_wait(chan, busy ? "vm-isonphone" : "vm-isunavail", ecodes); return res; -@@ -5670,6 +5679,7 @@ static int count_messages_in_folder(struct odbc_obj *odbc, const char *context, +@@ -6161,6 +6170,7 @@ static int count_messages_in_folder(struct odbc_obj *odbc, const char *context, } *messages = atoi(rowdata); + ast_log(LOG_DEBUG, "inboxcount/%s: %d\n", context, *messages); SQLFreeHandle(SQL_HANDLE_STMT, stmt); - return 0; -@@ -6096,10 +6106,11 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) + SCOPE_EXIT_RTN_VALUE(0, "messages: %d\n", *messages); +@@ -6609,10 +6619,11 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) return res; } @@ -115,7 +115,7 @@ index 9105e1a..c6ad060 100644 int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0; struct ast_smdi_mwi_message *mwi_msg; -@@ -6108,6 +6119,9 @@ static void run_externnotify(const char *context, const char *extension, const c +@@ -6621,6 +6632,9 @@ static void run_externnotify(const char *context, const char *extension, const c else ast_copy_string(ext_context, extension, sizeof(ext_context)); @@ -125,7 +125,7 @@ index 9105e1a..c6ad060 100644 if (smdi_iface) { if (ast_app_has_voicemail(ext_context, NULL)) ast_smdi_mwi_set(smdi_iface, extension); -@@ -6128,12 +6142,15 @@ static void run_externnotify(const char *context, const char *extension, const c +@@ -6641,12 +6655,15 @@ static void run_externnotify(const char *context, const char *extension, const c } if (!ast_strlen_zero(externnotify)) { @@ -142,7 +142,7 @@ index 9105e1a..c6ad060 100644 oldvoicemails, urgentvoicemails); ast_debug(1, "Executing %s\n", arguments); ast_safe_system(arguments); -@@ -6577,7 +6594,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ +@@ -7085,7 +7102,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ /* Setup pre-file if appropriate */ if (strcmp(vmu->context, "default")) @@ -151,7 +151,7 @@ index 9105e1a..c6ad060 100644 else ast_copy_string(ext_context, vmu->mailbox, sizeof(ext_context)); -@@ -6587,16 +6604,16 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ +@@ -7095,18 +7112,18 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ Depending on the flag set in options. */ if (ast_test_flag(options, OPT_BUSY_GREETING)) { @@ -161,19 +161,21 @@ index 9105e1a..c6ad060 100644 - snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, ext); + snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vmu->mailbox); } + ast_trace(-1, "prefile: %s\n", prefile); /* Set the path to the tmpfile as VM_SPOOL_DIR/context/ext/temp and attempt to create the folder structure. */ - snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, ext); -- if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) { + snprintf(tempfile, sizeof(tempfile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vmu->mailbox); + ast_trace(-1, "tempfile: %s\n", tempfile); +- if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, ext, "tmp"))) { + if ((res = create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp"))) { - ast_log(AST_LOG_WARNING, "Failed to make directory (%s)\n", tempfile); free_user(vmu); ast_free(tmp); -@@ -6609,7 +6626,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ - DISPOSE(tempfile, -1); + SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_WARNING, +@@ -7122,7 +7139,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + /* It's easier just to try to make it than to check for its existence */ #ifndef IMAP_STORAGE - create_dirpath(dir, sizeof(dir), vmu->context, ext, "INBOX"); @@ -181,25 +183,28 @@ index 9105e1a..c6ad060 100644 #else snprintf(dir, sizeof(dir), "%simap", VM_SPOOL_DIR); if (mkdir(dir, VOICEMAIL_DIR_MODE) && errno != EEXIST) { -@@ -6670,7 +6687,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ - #ifdef ODBC_STORAGE - int success = +@@ -7171,9 +7188,9 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + /* Play the beginning intro if desired */ + if (!ast_strlen_zero(prefile)) { + #if defined(ODBC_STORAGE) +- int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, ext, context); ++ int success = SCOPE_CALL_WITH_INT_RESULT(-1, RETRIEVE, prefile, -1, vmu->mailbox, context); + #elif defined(IMAP_STORAGE) +- SCOPE_CALL(-1, RETRIEVE, prefile, -1, ext, context); ++ SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, context); #endif -- RETRIEVE(prefile, -1, ext, context); -+ RETRIEVE(prefile, -1, vmu->mailbox, context); + if (ast_fileexists(prefile, NULL, NULL) > 0) { - if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1) { - /* We know we have a greeting at this point, so squelch the instructions -@@ -6689,7 +6706,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ +@@ -7194,7 +7211,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ #endif } else { - ast_debug(1, "%s doesn't exist, doing what we can\n", prefile); + ast_trace(-1, "%s doesn't exist, doing what we can\n", prefile); - res = invent_message(chan, vmu->context, ext, ast_test_flag(options, OPT_BUSY_GREETING), ecodes); + res = invent_message(chan, vmu->context, vmu->mailbox, vmu->dialed_num, ast_test_flag(options, OPT_BUSY_GREETING), ecodes); } - DISPOSE(prefile, -1); + SCOPE_CALL(-1, DISPOSE, prefile, -1); if (res < 0) { -@@ -6792,7 +6809,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ +@@ -7292,7 +7309,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ ast_free(tmp); return -1; } @@ -208,25 +213,25 @@ index 9105e1a..c6ad060 100644 /* It is possible under certain circumstances that inboxcount did not * create a vm_state when it was needed. This is a catchall which will * rarely be used. -@@ -6860,7 +6877,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ +@@ -7361,7 +7378,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL), "Unknown"); ast_store_realtime("voicemail_data", - "origmailbox", ext, + "origmailbox", vmu->mailbox, "context", ast_channel_context(chan), - "macrocontext", ast_channel_macrocontext(chan), "exten", ast_channel_exten(chan), -@@ -6900,7 +6917,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + "priority", priority, +@@ -7399,7 +7416,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ "origtime=%ld\n" "category=%s\n" "msg_id=%s\n", - ext, + vmu->mailbox, ast_channel_context(chan), - ast_channel_macrocontext(chan), ast_channel_exten(chan), -@@ -6928,7 +6945,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ + S_COR(ast_channel_redirecting(chan)->from.number.valid, +@@ -7428,7 +7445,7 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_ leaving the message. So we update the directory where we want this message to go. */ if (!strcmp(flag, "Urgent")) { @@ -235,7 +240,7 @@ index 9105e1a..c6ad060 100644 } if (txt) { -@@ -7160,7 +7177,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg +@@ -7665,7 +7682,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg return res; #else char *dir = vms->curdir; @@ -244,7 +249,7 @@ index 9105e1a..c6ad060 100644 char *context = vmu->context; char sfn[PATH_MAX]; char dfn[PATH_MAX]; -@@ -7824,186 +7841,6 @@ static int get_folder2(struct ast_channel *chan, char *fn, int start) +@@ -8338,197 +8355,6 @@ static int get_folder2(struct ast_channel *chan, char *fn, int start) return res; } @@ -266,8 +271,9 @@ index 9105e1a..c6ad060 100644 - * This is invoked from forward_message() when performing a forward operation (option 8 from main menu). - * \return zero on success, -1 on error. - */ --static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, int curmsg, char *vm_fmts, -- char *context, signed char record_gain, long *duration, struct vm_state *vms, char *flag) +-static int vm_forwardoptions(struct ast_channel *chan, struct ast_vm_user *vmu, char *curdir, +- int curmsg, char *vm_fmts, char *context, signed char record_gain, long *duration, +- struct vm_state *vms, char *flag) -{ - int cmd = 0; - int retries = 0, prepend_duration = 0, already_recorded = 0; @@ -281,9 +287,11 @@ index 9105e1a..c6ad060 100644 - const char *msg_id = NULL; -#endif - const char *duration_str; +- SCOPE_ENTER(3, "mbox: %s msgnum: %d curdir: %s", vmu->mailbox, curmsg, curdir); - - /* Must always populate duration correctly */ - make_file(msgfile, sizeof(msgfile), curdir, curmsg); +- ast_trace(-1, "msgfile: %s\n", msgfile); - strcpy(textfile, msgfile); - strcpy(backup, msgfile); - strcpy(backup_textfile, msgfile); @@ -320,8 +328,11 @@ index 9105e1a..c6ad060 100644 -#else - - /* prepend a message to the current message, update the metadata and return */ +- ast_trace(-1, "Prepending to message %d\n", curmsg); - - make_file(msgfile, sizeof(msgfile), curdir, curmsg); +- ast_trace(-1, "msgfile: %s\n", msgfile); +- - strcpy(textfile, msgfile); - strncat(textfile, ".txt", sizeof(textfile) - 1); - *duration = 0; @@ -335,10 +346,12 @@ index 9105e1a..c6ad060 100644 - /* Back up the original file, so we can retry the prepend and restore it after forward. */ -#ifndef IMAP_STORAGE - if (already_recorded) { +- ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile); - ast_filecopy(backup, msgfile, NULL); - copy(backup_textfile, textfile); - } - else { +- ast_trace(-1, "Backing up '%s' to '%s'\n", backup, msgfile); - ast_filecopy(msgfile, backup, NULL); - copy(textfile, backup_textfile); - } @@ -348,7 +361,7 @@ index 9105e1a..c6ad060 100644 - if (record_gain) - ast_channel_setoption(chan, AST_OPTION_RXGAIN, &record_gain, sizeof(record_gain), 0); - -- cmd = ast_play_and_prepend(chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence); +- cmd = SCOPE_CALL_WITH_INT_RESULT(-1, ast_play_and_prepend, chan, NULL, msgfile, 0, vm_fmts, &prepend_duration, NULL, 1, silencethreshold, maxsilence); - - if (cmd == 'S') { /* If we timed out, tell the user it didn't work properly and clean up the files */ - ast_stream_and_wait(chan, vm_pls_try_again, ""); /* this might be removed if a proper vm_prepend_timeout is ever recorded */ @@ -369,6 +382,7 @@ index 9105e1a..c6ad060 100644 - char duration_buf[12]; - - *duration += prepend_duration; +- ast_trace(-1, "Prepending duration: %d total duration: %ld\n", prepend_duration, *duration); - msg_cat = ast_category_get(msg_cfg, "message", NULL); - snprintf(duration_buf, sizeof(duration_buf), "%ld", *duration); - if (!ast_variable_update(msg_cat, "duration", duration_buf, NULL, 0)) { @@ -419,19 +433,21 @@ index 9105e1a..c6ad060 100644 - - if (already_recorded && cmd == -1) { - /* restore original message if prepention cancelled */ +- ast_trace(-1, "Restoring '%s' to '%s'\n", backup, msgfile); - ast_filerename(backup, msgfile, NULL); - rename(backup_textfile, textfile); - } - -- if (cmd == 't' || cmd == 'S') /* XXX entering this block with a value of 'S' is probably no longer possible. */ +- if (cmd == 't' || cmd == 'S') { /* XXX entering this block with a value of 'S' is probably no longer possible. */ - cmd = 0; -- return cmd; +- } +- SCOPE_EXIT_RTN_VALUE(cmd, "Done. CMD: %d %c\n", cmd, cmd >= 32 && cmd < 127 ? cmd : '?'); -} - static void queue_mwi_event(const char *channel_id, const char *box, int urgent, int new, int old) { char *mailbox; -@@ -8123,7 +7960,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8648,7 +8474,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs); @@ -440,7 +456,7 @@ index 9105e1a..c6ad060 100644 #ifdef IMAP_STORAGE vm_delete(fn); /* Delete the file, but not the IMAP message */ -@@ -8136,373 +7973,6 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8661,378 +8487,6 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, return 0; } @@ -495,11 +511,16 @@ index 9105e1a..c6ad060 100644 -#ifndef IMAP_STORAGE - char msgfile[PATH_MAX], textfile[PATH_MAX], backup[PATH_MAX], backup_textfile[PATH_MAX]; -#endif +- SCOPE_ENTER(3, "%s: user: %s dir: %s msg: %d\n", ast_channel_name(chan), +- vms->username, vms->curdir, vms->curmsg); +- - if (ast_test_flag((&globalflags), VM_FWDURGAUTO)) { - ast_copy_string(urgent_str, urgent ? "Urgent" : "", sizeof(urgent_str)); - } - -- if (vms == NULL) return -1; +- if (vms == NULL) { +- SCOPE_EXIT_RTN_VALUE(-1, "vms is NULL\n"); +- } - dir = vms->curdir; - curmsg = vms->curmsg; - @@ -661,17 +682,17 @@ index 9105e1a..c6ad060 100644 - - /* play name if available, else play extension number */ - snprintf(fn, sizeof(fn), "%s%s/%s/greet", VM_SPOOL_DIR, receiver->context, s); -- RETRIEVE(fn, -1, s, receiver->context); +- SCOPE_CALL(-1, RETRIEVE, fn, -1, s, receiver->context); - if (ast_fileexists(fn, NULL, NULL) > 0) { - res = ast_stream_and_wait(chan, fn, ecodes); - if (res) { -- DISPOSE(fn, -1); +- SCOPE_CALL(-1, DISPOSE, fn, -1); - return res; - } - } else { - res = ast_say_digit_str(chan, s, ecodes, ast_channel_language(chan)); - } -- DISPOSE(fn, -1); +- SCOPE_CALL(-1, DISPOSE, fn, -1); - - s = strsep(&stringp, "*"); - } @@ -691,7 +712,7 @@ index 9105e1a..c6ad060 100644 - memset(&leave_options, 0, sizeof(leave_options)); - leave_options.record_gain = record_gain; - leave_options.beeptone = "beep"; -- cmd = leave_voicemail(chan, mailbox, &leave_options); +- cmd = SCOPE_CALL_WITH_INT_RESULT(-1, leave_voicemail, chan, mailbox, &leave_options); - } else { - /* Forward VoiceMail */ - long duration = 0; @@ -705,7 +726,7 @@ index 9105e1a..c6ad060 100644 -#endif - memcpy(&vmstmp, vms, sizeof(vmstmp)); - -- RETRIEVE(dir, curmsg, sender->mailbox, sender->context); +- SCOPE_CALL(-1, RETRIEVE, dir, curmsg, sender->mailbox, sender->context); -#ifdef IMAP_STORAGE - make_file(filename, sizeof(filename), dir, curmsg); - strncat(filename, ".txt", sizeof(filename) - strlen(filename) - 1); @@ -716,7 +737,7 @@ index 9105e1a..c6ad060 100644 - } -#endif - -- cmd = vm_forwardoptions(chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str); +- cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_forwardoptions, chan, sender, vmstmp.curdir, curmsg, vmfmts, S_OR(context, "default"), record_gain, &duration, &vmstmp, urgent_str); - if (!cmd) { - AST_LIST_TRAVERSE_SAFE_BEGIN(&extensions, vmtmp, list) { -#ifdef IMAP_STORAGE @@ -750,7 +771,7 @@ index 9105e1a..c6ad060 100644 - vmstmp.fn, vmstmp.introfn, fmt, duration, attach_user_voicemail, chan, - NULL, urgent_str, msg_id); -#else -- copy_msg_result = copy_message(chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL); +- copy_msg_result = SCOPE_CALL_WITH_INT_RESULT(-1, copy_message, chan, sender, 0, curmsg, duration, vmtmp, fmt, dir, urgent_str, NULL); -#endif - saved_messages++; - AST_LIST_REMOVE_CURRENT(list); @@ -790,7 +811,7 @@ index 9105e1a..c6ad060 100644 - } -#endif - } -- DISPOSE(dir, curmsg); +- SCOPE_CALL(-1, DISPOSE, dir, curmsg); -#ifndef IMAP_STORAGE - if (cmd) { /* assuming hangup, cleanup backup file */ - make_file(msgfile, sizeof(msgfile), dir, curmsg); @@ -808,13 +829,13 @@ index 9105e1a..c6ad060 100644 - inprocess_count(vmtmp->mailbox, vmtmp->context, -1); - free_user(vmtmp); - } -- return res ? res : cmd; +- SCOPE_EXIT_RTN_VALUE(res ? res : cmd, "Done. res: %d cmd: %d\n", res, cmd); -} - static int wait_file2(struct ast_channel *chan, struct vm_state *vms, char *file) { int res; -@@ -9007,7 +8477,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) +@@ -9537,7 +8991,7 @@ static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu, int box) snprintf(vms->vmbox, sizeof(vms->vmbox), "vm-%s", vms->curbox); /* Faster to make the directory than to check if it exists. */ @@ -822,8 +843,8 @@ index 9105e1a..c6ad060 100644 + create_dirpath(vms->curdir, sizeof(vms->curdir), vmu->context, vmu->mailbox, vms->curbox); /* traverses directory using readdir (or select query for ODBC) */ - count_msg = count_messages(vmu, vms->curdir); -@@ -10307,7 +9777,7 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm + count_msg = COUNT(vmu, vms->curdir); +@@ -10842,7 +10296,7 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm char prefile[256]; /* Notify the user that the temp greeting is set and give them the option to remove it */ @@ -832,7 +853,7 @@ index 9105e1a..c6ad060 100644 if (ast_test_flag(vmu, VM_TEMPGREETWARN)) { RETRIEVE(prefile, -1, vmu->mailbox, vmu->context); if (ast_fileexists(prefile, NULL, NULL) > 0) { -@@ -10437,9 +9907,6 @@ static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -10972,9 +10426,6 @@ static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, res = ast_play_and_wait(chan, "vm-undelete"); } } @@ -842,7 +863,7 @@ index 9105e1a..c6ad060 100644 if (!res) { res = ast_play_and_wait(chan, "vm-savemessage"); } -@@ -10530,9 +9997,6 @@ static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -11065,9 +10516,6 @@ static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, } else { res = ast_play_and_wait(chan, "vm-undelete"); } @@ -852,7 +873,7 @@ index 9105e1a..c6ad060 100644 if (!res) { res = ast_play_and_wait(chan, "vm-savemessage"); } -@@ -10614,7 +10078,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s +@@ -11149,7 +10597,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s /* If forcename is set, have the user record their name */ if (ast_test_flag(vmu, VM_FORCENAME)) { @@ -861,7 +882,7 @@ index 9105e1a..c6ad060 100644 if (ast_fileexists(prefile, NULL, NULL) < 1) { cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); if (cmd < 0 || cmd == 't' || cmd == '#') -@@ -10624,14 +10088,14 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s +@@ -11159,14 +10607,14 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s /* If forcegreetings is set, have the user record their greetings */ if (ast_test_flag(vmu, VM_FORCEGREET)) { @@ -878,7 +899,7 @@ index 9105e1a..c6ad060 100644 if (ast_fileexists(prefile, NULL, NULL) < 1) { cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); if (cmd < 0 || cmd == 't' || cmd == '#') -@@ -10655,7 +10119,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s +@@ -11190,7 +10638,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s return cmd; cmd = check_password(vmu, newpassword); /* perform password validation */ if (cmd != 0) { @@ -887,7 +908,7 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_invalid_password); } else { newpassword2[1] = '\0'; -@@ -10669,7 +10133,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s +@@ -11204,7 +10652,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s return cmd; if (!strcmp(newpassword, newpassword2)) break; @@ -896,7 +917,7 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_mismatch); } if (++tries == 3) -@@ -10683,7 +10147,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s +@@ -11218,7 +10666,7 @@ static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, s if ((pwdchange & PWDCHANGE_EXTERNAL) && !ast_strlen_zero(ext_pass_cmd)) vm_change_password_shell(vmu, newpassword); @@ -905,26 +926,26 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_passchanged); return cmd; -@@ -10714,15 +10178,15 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct +@@ -11250,15 +10698,15 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct retries = 0; switch (cmd) { case '1': /* Record your unavailable message */ - snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vms->username); + snprintf(prefile, sizeof(prefile), "%s%s/%s/unavail", VM_SPOOL_DIR, vmu->context, vmu->mailbox); - cmd = play_record_review(chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-unv", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '2': /* Record your busy message */ - snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vms->username); + snprintf(prefile, sizeof(prefile), "%s%s/%s/busy", VM_SPOOL_DIR, vmu->context, vmu->mailbox); - cmd = play_record_review(chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-busy", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '3': /* Record greeting */ - snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vms->username); + snprintf(prefile, sizeof(prefile), "%s%s/%s/greet", VM_SPOOL_DIR, vmu->context, vmu->mailbox); - cmd = play_record_review(chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, play_record_review, chan, "vm-rec-name", prefile, maxgreet, fmtc, 0, vmu, &duration, NULL, NULL, record_gain, vms, NULL, NULL, 0); break; case '4': /* manage the temporary greeting */ -@@ -10746,7 +10210,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct +@@ -11282,7 +10730,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct } cmd = check_password(vmu, newpassword); /* perform password validation */ if (cmd != 0) { @@ -933,7 +954,7 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_invalid_password); if (!cmd) { cmd = ast_play_and_wait(chan, vm_pls_try_again); -@@ -10766,7 +10230,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct +@@ -11302,7 +10750,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct } } if (strcmp(newpassword, newpassword2)) { @@ -942,7 +963,7 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_mismatch); if (!cmd) { cmd = ast_play_and_wait(chan, vm_pls_try_again); -@@ -10782,7 +10246,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct +@@ -11318,7 +10766,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct } ast_debug(1, "User %s set password to %s of length %d\n", @@ -951,16 +972,16 @@ index 9105e1a..c6ad060 100644 cmd = ast_play_and_wait(chan, vm_passchanged); break; case '*': -@@ -10790,7 +10254,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct +@@ -11326,7 +10774,7 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct break; default: cmd = 0; - snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vms->username); + snprintf(prefile, sizeof(prefile), "%s%s/%s/temp", VM_SPOOL_DIR, vmu->context, vmu->mailbox); - RETRIEVE(prefile, -1, vmu->mailbox, vmu->context); + SCOPE_CALL(-1, RETRIEVE, prefile, -1, vmu->mailbox, vmu->context); if (ast_fileexists(prefile, NULL, NULL)) { cmd = ast_play_and_wait(chan, "vm-tmpexists"); -@@ -10852,7 +10316,7 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st +@@ -11388,7 +10836,7 @@ static int vm_tempgreeting(struct ast_channel *chan, struct ast_vm_user *vmu, st } ast_test_suite_event_notify("TEMPGREETING", "Message: entering temp greeting options"); @@ -969,7 +990,7 @@ index 9105e1a..c6ad060 100644 while ((cmd >= 0) && (cmd != 't')) { if (cmd) retries = 0; -@@ -11778,35 +11242,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12710,37 +12158,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) vms.repeats = 0; while ((cmd > -1) && (cmd != 't') && (cmd != '#')) { switch (cmd) { @@ -978,6 +999,7 @@ index 9105e1a..c6ad060 100644 - cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 1, record_gain); - if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) { - res = cmd; +- ast_trace(-1, "advanced options: %d\n", cmd); - goto out; - } - } else { @@ -990,6 +1012,7 @@ index 9105e1a..c6ad060 100644 - ast_verb(3, "Callback Requested\n"); - if (!ast_strlen_zero(vmu->callback) && vms.lastmsg > -1 && !vms.starting) { - cmd = advanced_options(chan, vmu, &vms, vms.curmsg, 2, record_gain); +- ast_trace(-1, "advanced options: %d\n", cmd); - if (cmd == 9) { - silentexit = 1; - goto out; @@ -1005,7 +1028,7 @@ index 9105e1a..c6ad060 100644 case '3': /* Envelope */ if (vms.lastmsg > -1 && !vms.starting) { ast_safe_sleep(chan, 500); -@@ -11820,32 +11255,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12755,34 +12172,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) } cmd = 't'; break; @@ -1014,6 +1037,7 @@ index 9105e1a..c6ad060 100644 - cmd = dialout(chan, vmu, NULL, vmu->dialout); - if (cmd == 9) { - silentexit = 1; +- ast_trace(-1, "dialout: %d\n", cmd); - goto out; - } - } else { @@ -1024,9 +1048,10 @@ index 9105e1a..c6ad060 100644 - - case '5': /* Leave VoiceMail */ - if (ast_test_flag(vmu, VM_SVMAIL)) { -- cmd = forward_message(chan, context, &vms, vmu, vmfmts, 1, record_gain, 0); +- cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 1, record_gain, 0); - if (cmd == ERROR_LOCK_PATH || cmd == OPERATOR_EXIT) { - res = cmd; +- ast_trace(-1, "forward message: %d\n", cmd); - goto out; - } - } else { @@ -1038,7 +1063,7 @@ index 9105e1a..c6ad060 100644 case '*': /* Return to main menu */ cmd = 't'; break; -@@ -11853,21 +11262,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12790,21 +12179,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data) default: ast_safe_sleep(chan, 500); cmd = 0; @@ -1060,15 +1085,16 @@ index 9105e1a..c6ad060 100644 if (!cmd) { cmd = ast_play_and_wait(chan, "vm-starmain"); } -@@ -12018,37 +11415,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -12967,42 +12344,6 @@ static int vm_execmain(struct ast_channel *chan, const char *data) #endif break; - case '8': /* Forward the current message */ - if (vms.lastmsg > -1) { -- cmd = forward_message(chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent); +- cmd = SCOPE_CALL_WITH_INT_RESULT(-1, forward_message, chan, context, &vms, vmu, vmfmts, 0, record_gain, in_urgent); - if (cmd == ERROR_LOCK_PATH) { - res = cmd; +- ast_trace(-1, "forward message: %d\n", res); - goto out; - } - } else { @@ -1079,12 +1105,16 @@ index 9105e1a..c6ad060 100644 - if (in_urgent == 1 && vms.newmessages > 0) { - /* Check for new messages */ - in_urgent = 0; -- res = close_mailbox(&vms, vmu); -- if (res == ERROR_LOCK_PATH) +- res = SCOPE_CALL_WITH_INT_RESULT(-1, close_mailbox, &vms, vmu); +- if (res == ERROR_LOCK_PATH) { +- ast_trace(-1, "close mailbox: %d\n", res); - goto out; -- res = open_mailbox(&vms, vmu, NEW_FOLDER); -- if (res < 0) +- } +- res = SCOPE_CALL_WITH_INT_RESULT(-1, open_mailbox, &vms, vmu, NEW_FOLDER); +- if (res < 0) { +- ast_trace(-1, "open mailbox: %d\n", res); - goto out; +- } - ast_debug(1, "No more urgent messages, opened INBOX and got %d new messages\n", vms.lastmsg + 1); - vms.curmsg = -1; - if (vms.lastmsg < 0) { @@ -1098,15 +1128,15 @@ index 9105e1a..c6ad060 100644 case '9': /* Save message to folder */ ast_test_suite_event_notify("SAVEMSG", "Message: saving message %d\r\nVoicemail: %d", vms.curmsg, vms.curmsg); if (vms.curmsg < 0 || vms.curmsg > vms.lastmsg) { -@@ -12159,6 +11525,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) +@@ -13118,6 +12459,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data) cmd = 0; break; case '0': /* Mailbox options */ + ast_log(LOG_DEBUG, "setting options for '%s'", vmu->mailbox); - cmd = vm_options(chan, vmu, &vms, vmfmts, record_gain); + cmd = SCOPE_CALL_WITH_INT_RESULT(-1, vm_options,chan, vmu, &vms, vmfmts, record_gain); if (useadsi) adsi_status(chan, &vms); -@@ -12205,7 +11572,7 @@ out: +@@ -13166,7 +12508,7 @@ out: int new = 0, old = 0, urgent = 0; snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context); /* Urgent flag not passwd to externnotify here */ @@ -1115,7 +1145,7 @@ index 9105e1a..c6ad060 100644 ast_app_inboxcount2(ext_context, &urgent, &new, &old); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old); } -@@ -13027,7 +12394,6 @@ static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data) +@@ -14006,7 +13348,6 @@ static int poll_subscribed_mailbox(struct ast_mwi_state *mwi_state, void *data) if (urgent != mwi_state->urgent_msgs || new != mwi_state->new_msgs || old != mwi_state->old_msgs) { queue_mwi_event(NULL, mwi_state->uniqueid, urgent, new, old); @@ -1123,7 +1153,7 @@ index 9105e1a..c6ad060 100644 } return 0; -@@ -16104,7 +15470,7 @@ static void notify_new_state(struct ast_vm_user *vmu) +@@ -17345,7 +16686,7 @@ static void notify_new_state(struct ast_vm_user *vmu) char ext_context[1024]; snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context); diff --git a/debian/patches/sipwise_vm_vmnotify_ext_format.patch b/debian/patches/sipwise_vm_vmnotify_ext_format.patch index 5e18142..bb5465f 100644 --- a/debian/patches/sipwise_vm_vmnotify_ext_format.patch +++ b/debian/patches/sipwise_vm_vmnotify_ext_format.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_vmnotify_ext_format 1 file changed, 97 insertions(+), 36 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 70478fa..f26bbfa 100644 +index 0d63f1e..72aa606 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -1091,6 +1091,8 @@ static int vm_msg_move(const char *mailbox, const char *context, size_t num_msgs +@@ -1231,6 +1231,8 @@ static int vm_msg_move(const char *mailbox, const char *context, size_t num_msgs static int vm_msg_remove(const char *mailbox, const char *context, size_t num_msgs, const char *folder, const char *msgs[]); static int vm_msg_play(struct ast_channel *chan, const char *mailbox, const char *context, const char *folder, const char *msg_num, ast_vm_msg_play_cb cb); @@ -19,7 +19,7 @@ index 70478fa..f26bbfa 100644 #ifdef TEST_FRAMEWORK static int vm_test_destroy_user(const char *context, const char *mailbox); static int vm_test_create_user(const char *context, const char *mailbox); -@@ -5656,7 +5658,7 @@ static int sendmail(char *srcemail, +@@ -6145,7 +6147,7 @@ static int sendmail(char *srcemail, return 0; } @@ -28,7 +28,7 @@ index 70478fa..f26bbfa 100644 { char arguments[2048]; char date[256]; -@@ -5665,6 +5667,7 @@ static void run_externpager(char *pager, char *dialed_num, char *cidnum, int dur +@@ -6154,6 +6156,7 @@ static void run_externpager(char *pager, char *dialed_num, char *cidnum, int dur char dur[PATH_MAX]; struct ast_tm tm; struct ast_str *str1 = ast_str_create(16); @@ -36,7 +36,7 @@ index 70478fa..f26bbfa 100644 if (!str1) { return; -@@ -5680,8 +5683,14 @@ static void run_externpager(char *pager, char *dialed_num, char *cidnum, int dur +@@ -6169,8 +6172,14 @@ static void run_externpager(char *pager, char *dialed_num, char *cidnum, int dur snprintf(dur, sizeof(dur), "%d:%02d", duration / 60, duration % 60); @@ -53,7 +53,7 @@ index 70478fa..f26bbfa 100644 if (pagerbody) { struct ast_channel *ast; -@@ -6236,9 +6245,11 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) +@@ -6746,9 +6755,11 @@ static int inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs) return res; } @@ -67,7 +67,7 @@ index 70478fa..f26bbfa 100644 char ext_context[256] = ""; char number[256] = ""; int newvoicemails = 0, oldvoicemails = 0, urgentvoicemails = 0; -@@ -6278,10 +6289,20 @@ static void run_externnotify(const char *context, const char *extension, const c +@@ -6788,10 +6799,20 @@ static void run_externnotify(const char *context, const char *extension, const c } else if (ast_strlen_zero(number) || !strcmp(extension, number)) { ast_log(AST_LOG_WARNING, "Missing user number to run externnotify on context '%s'\n", ext_context); } else { @@ -92,7 +92,7 @@ index 70478fa..f26bbfa 100644 ast_debug(1, "Executing %s\n", arguments); ast_safe_system(arguments); } -@@ -8002,6 +8023,59 @@ static void queue_mwi_event(const char *channel_id, const char *box, int urgent, +@@ -8513,6 +8534,59 @@ static void queue_mwi_event(const char *channel_id, const char *box, int urgent, } } @@ -152,7 +152,7 @@ index 70478fa..f26bbfa 100644 /*! * \brief Sends email notification that a user has a new voicemail waiting for them. * \param chan -@@ -8022,6 +8096,8 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8533,6 +8607,8 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int newmsgs = 0, oldmsgs = 0, urgentmsgs = 0; const char *category; char *myserveremail = serveremail; @@ -161,7 +161,7 @@ index 70478fa..f26bbfa 100644 ast_channel_lock(chan); if ((category = pbx_builtin_getvar_helper(chan, "VM_CATEGORY"))) { -@@ -8079,7 +8155,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8590,7 +8666,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, } if (!ast_strlen_zero(vmu->pager)) { @@ -170,7 +170,7 @@ index 70478fa..f26bbfa 100644 } if (ast_test_flag(vmu, VM_DELETE)) -@@ -8090,7 +8166,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, +@@ -8601,7 +8677,7 @@ static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, ast_app_inboxcount2(ext_context, &urgentmsgs, &newmsgs, &oldmsgs); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgentmsgs, newmsgs, oldmsgs); @@ -179,7 +179,7 @@ index 70478fa..f26bbfa 100644 #ifdef IMAP_STORAGE vm_delete(fn); /* Delete the file, but not the IMAP message */ -@@ -8135,35 +8211,20 @@ static int play_message_category(struct ast_channel *chan, const char *category) +@@ -8646,35 +8722,20 @@ static int play_message_category(struct ast_channel *chan, const char *category) static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename) { int res = 0; @@ -221,7 +221,7 @@ index 70478fa..f26bbfa 100644 /* No internal variable parsing for now, so we'll comment it out for the time being */ #if 0 /* Set the DIFF_* variables */ -@@ -8180,8 +8241,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v +@@ -8691,8 +8752,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */ #endif @@ -232,7 +232,7 @@ index 70478fa..f26bbfa 100644 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */ -@@ -11820,7 +11881,7 @@ out: +@@ -12753,7 +12814,7 @@ out: int new = 0, old = 0, urgent = 0; snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context); /* Urgent flag not passwd to externnotify here */ @@ -241,7 +241,7 @@ index 70478fa..f26bbfa 100644 ast_app_inboxcount2(ext_context, &urgent, &new, &old); queue_mwi_event(ast_channel_uniqueid(chan), ext_context, urgent, new, old); } -@@ -15737,7 +15798,7 @@ static void notify_new_state(struct ast_vm_user *vmu) +@@ -16950,7 +17011,7 @@ static void notify_new_state(struct ast_vm_user *vmu) char ext_context[1024]; snprintf(ext_context, sizeof(ext_context), "%s@%s", vmu->mailbox, vmu->context); diff --git a/debian/patches/sipwise_vm_zonemessages.patch b/debian/patches/sipwise_vm_zonemessages.patch index 4e120ae..f20558d 100644 --- a/debian/patches/sipwise_vm_zonemessages.patch +++ b/debian/patches/sipwise_vm_zonemessages.patch @@ -7,10 +7,10 @@ Subject: sipwise_vm_zonemessages 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c -index 33dc99c..70478fa 100644 +index e3182eb..0d63f1e 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c -@@ -8135,7 +8135,7 @@ static int play_message_category(struct ast_channel *chan, const char *category) +@@ -8646,7 +8646,7 @@ static int play_message_category(struct ast_channel *chan, const char *category) static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *vmu, const char *origtime, const char *filename) { int res = 0; @@ -19,7 +19,7 @@ index 33dc99c..70478fa 100644 time_t t; if (ast_get_time_t(origtime, &t, 0, NULL)) { -@@ -8150,13 +8150,20 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v +@@ -8661,13 +8661,20 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v AST_LIST_LOCK(&zones); AST_LIST_TRAVERSE(&zones, z, list) { if (!strcmp(z->name, vmu->zonetag)) { @@ -41,7 +41,7 @@ index 33dc99c..70478fa 100644 /* No internal variable parsing for now, so we'll comment it out for the time being */ #if 0 /* Set the DIFF_* variables */ -@@ -8173,8 +8180,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v +@@ -8684,8 +8691,8 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v /* Can't think of how other diffs might be helpful, but I'm sure somebody will think of something. */ #endif @@ -52,7 +52,7 @@ index 33dc99c..70478fa 100644 } else if (!strncasecmp(ast_channel_language(chan), "de", 2)) { /* GERMAN syntax */ res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL); } else if (!strncasecmp(ast_channel_language(chan), "gr", 2)) { /* GREEK syntax */ -@@ -13210,17 +13217,14 @@ static void load_zonemessages(struct ast_config *cfg) +@@ -14385,17 +14392,14 @@ static void load_zonemessages(struct ast_config *cfg) strcpy(storage, var->value); /* safe */ msg_format = storage; tzone = strsep(&msg_format, "|,");