Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 319757) +++ apps/app_voicemail.c (working copy) @@ -2473,7 +2473,6 @@ fprintf(f, "[message]\n"); for (x=0;x -1) @@ -2560,8 +2559,7 @@ struct odbc_obj *obj; obj = ast_odbc_request_obj(odbc_database, 0); if (obj) { - snprintf(sql, sizeof(sql), "SELECT msgnum FROM %s WHERE dir=? order by msgnum desc limit 1", odbc_table); - + 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(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); @@ -2570,12 +2568,7 @@ } res = SQLFetch(stmt); if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (res == SQL_NO_DATA) { - ast_log(LOG_DEBUG, "Directory '%s' has no messages and therefore no index was retrieved.\n", dir); - } else { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - } - + ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); SQLFreeHandle (SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); goto yuck; @@ -2588,13 +2581,12 @@ goto yuck; } if (sscanf(rowdata, "%30d", &x) != 1) - ast_log(LOG_WARNING, "Failed to read message index!\n"); + ast_log(LOG_WARNING, "Failed to read message count!\n"); SQLFreeHandle (SQL_HANDLE_STMT, stmt); ast_odbc_release_obj(obj); - return x; } else ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: +yuck: return x - 1; } @@ -2640,54 +2632,13 @@ ast_odbc_release_obj(obj); } else ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: +yuck: return x; } static int count_messages(struct ast_vm_user *vmu, char *dir) { - int x = 0; - int res; - SQLHSTMT stmt; - char sql[PATH_MAX]; - char rowdata[20]; - char *argv[] = { dir }; - struct generic_prepare_struct gps = { .sql = sql, .argc = 1, .argv = argv }; - - struct odbc_obj *obj; - obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); - ast_odbc_release_obj(obj); - goto yuck; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - if (sscanf(rowdata, "%30d", &x) != 1) - ast_log(LOG_WARNING, "Failed to read message count!\n"); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - return x; - } else - ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: - return x - 1; - + return last_message_index(vmu, dir) + 1; } static void delete_file(char *sdir, int smsg) @@ -2882,7 +2833,7 @@ ast_odbc_release_obj(obj); } else ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: +yuck: if (cfg) ast_config_destroy(cfg); if (fdm != MAP_FAILED) @@ -2955,54 +2906,24 @@ } #endif -/*! - * \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). - * Typical use to set the msgnum would be to take the value returned from this method and add one to it. - * - * \note Should always be called with a lock already set on dir. - * \return the value of zero or greater to indicate the last message index in use, -1 to indicate none. +/* + * A negative return value indicates an error. */ #if (!defined(IMAP_STORAGE) && !defined(ODBC_STORAGE)) static int last_message_index(struct ast_vm_user *vmu, char *dir) { int x; - unsigned char map[MAXMSGLIMIT] = ""; - DIR *msgdir; - struct dirent *msgdirent; - int msgdirint; - char extension[4]; - int stopcount = 0; + char fn[PATH_MAX]; - /* Reading the entire directory into a file map scales better than - * doing a stat repeatedly on a predicted sequence. I suspect this - * is partially due to stat(2) internally doing a readdir(2) itself to - * find each file. */ - if (!(msgdir = opendir(dir))) { - return -1; - } + if (vm_lock_path(dir)) + return ERROR_LOCK_PATH; - while ((msgdirent = readdir(msgdir))) { - if (sscanf(msgdirent->d_name, "msg%30d.%3s", &msgdirint, extension) == 2 && !strcmp(extension, "txt") && msgdirint < MAXMSGLIMIT) { - map[msgdirint] = 1; - stopcount++; - if (option_debug > 3) { - ast_log(LOG_DEBUG, "%s map[%d] = %d, count = %d\n", dir, msgdirint, map[msgdirint], stopcount); - } - } - } - closedir(msgdir); - for (x = 0; x < vmu->maxmsg; x++) { - if (map[x] == 1) { - stopcount--; - } else if (map[x] == 0 && !stopcount) { + make_file(fn, sizeof(fn), dir, x); + if (ast_fileexists(fn, NULL, NULL) < 1) break; - } } + ast_unlock_path(dir); return x - 1; } @@ -3641,8 +3562,7 @@ char *ctype = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-"; char tmpdir[256], newtmp[256]; int tmpfd = -1; - int soxstatus = 0; - + if (vmu->volgain < -.001 || vmu->volgain > .001) { create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp"); snprintf(newtmp, sizeof(newtmp), "%s/XXXXXX", tmpdir); @@ -3651,6 +3571,7 @@ if (option_debug > 2) ast_log(LOG_DEBUG, "newtmp: %s\n", newtmp); if (tmpfd > -1) { + int soxstatus; snprintf(tmpcmd, sizeof(tmpcmd), "sox -v %.4f %s.%s %s.%s", vmu->volgain, attach, format, newtmp, format); if ((soxstatus = ast_safe_system(tmpcmd)) == 0) { attach = newtmp; @@ -3673,9 +3594,7 @@ base_encode(fname, p); fprintf(p, ENDL "--%s--" ENDL "." ENDL, bound); if (tmpfd > -1) { - if (soxstatus == 0) { - unlink(fname); - } + unlink(fname); close(tmpfd); unlink(newtmp); } @@ -3961,7 +3880,7 @@ } else ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: +yuck: return x; } @@ -4536,10 +4455,12 @@ ast_unlock_path(dir); inprocess_count(vmu->mailbox, vmu->context, -1); } else { -#ifndef IMAP_STORAGE - msgnum = last_message_index(vmu, dir) + 1; -#endif - make_file(fn, sizeof(fn), dir, msgnum); + for (;;) { + make_file(fn, sizeof(fn), dir, msgnum); + if (!EXISTS(dir, msgnum, fn, NULL)) + break; + msgnum++; + } /* assign a variable with the name of the voicemail file */ #ifndef IMAP_STORAGE @@ -4605,10 +4526,10 @@ return res; } -#if !defined(IMAP_STORAGE) -static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int stopcount) +#ifndef IMAP_STORAGE +static int resequence_mailbox(struct ast_vm_user *vmu, char *dir, int count_msg) { - /* we know the actual number of messages, so stop process when number is hit */ + /* we know max messages, so stop process when number is hit */ int x,dest; char sfn[PATH_MAX]; @@ -4617,7 +4538,7 @@ if (vm_lock_path(dir)) return ERROR_LOCK_PATH; - for (x = 0, dest = 0; dest != stopcount && x < vmu->maxmsg + 10; x++) { + for (x = 0, dest = 0; x < count_msg + 1; x++) { make_file(sfn, sizeof(sfn), dir, x); if (EXISTS(dir, x, sfn, NULL)) { @@ -5283,7 +5204,6 @@ prepend_duration = 0; /* Back up the original file, so we can retry the prepend */ -#ifndef IMAP_STORAGE if (already_recorded) { ast_filecopy(backup, msgfile, NULL); copy(textfile, backup_textfile); @@ -5291,7 +5211,6 @@ ast_filecopy(msgfile, backup, NULL); copy(textfile, backup_textfile); } -#endif already_recorded = 1; if (record_gain) @@ -5437,6 +5356,7 @@ char *dir; int curmsg; int prompt_played = 0; + char lm_users[4096] = ""; if (vms == NULL) return -1; dir = vms->curdir; @@ -5558,6 +5478,19 @@ break; } AST_LIST_INSERT_HEAD(&extensions, receiver, list); + // Add to list of users to leave voicemail for + if ((strlen(lm_users) + strlen(s) + 2) < 4090) { + if (strlen(lm_users) > 0) { + strcat(lm_users, "&"); + } + strcat(lm_users, s); + if (context) { + if ((strlen(lm_users) + strlen(context) + 2) < 4090) { + strcat(lm_users, "@"); + strcat(lm_users, context); + } + } + } } else { ast_log(LOG_NOTICE, "'%s' is not a valid mailbox\n", s); /* "I am sorry, that's not a valid extension. Please try again." */ @@ -5576,17 +5509,10 @@ return res; if (is_new_message == 1) { struct leave_vm_options leave_options; - char mailbox[AST_MAX_EXTENSION * 2 + 2]; - /* Make sure that context doesn't get set as a literal "(null)" (or else find_user won't find it) */ - if (context) - snprintf(mailbox, sizeof(mailbox), "%s@%s", username, context); - else - ast_copy_string(mailbox, username, sizeof(mailbox)); - /* Send VoiceMail */ memset(&leave_options, 0, sizeof(leave_options)); leave_options.record_gain = record_gain; - cmd = leave_voicemail(chan, mailbox, &leave_options); + cmd = leave_voicemail(chan, lm_users, &leave_options); } else { /* Forward VoiceMail */ long duration = 0; @@ -6045,6 +5971,7 @@ #ifndef IMAP_STORAGE static int open_mailbox(struct vm_state *vms, struct ast_vm_user *vmu,int box) { + int res = 0; int count_msg, last_msg; ast_copy_string(vms->curbox, mbox(box), sizeof(vms->curbox)); @@ -6077,12 +6004,12 @@ /* for local storage, checks directory for messages up to maxmsg limit */ last_msg = last_message_index(vmu, vms->curdir); - - if (last_msg < -1) { + if (last_msg < -1) return last_msg; - } else if (vms->lastmsg != 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); + res = resequence_mailbox(vmu, vms->curdir, count_msg); } return 0; @@ -6093,7 +6020,6 @@ { int x = 0; #ifndef IMAP_STORAGE - int last_msg_index; int res = 0, nummsg; #endif @@ -6105,14 +6031,9 @@ /* Get the deleted messages fixed */ if (vm_lock_path(vms->curdir)) return ERROR_LOCK_PATH; - - last_msg_index = last_message_index(vmu, vms->curdir); - if (last_msg_index != vms->lastmsg) { - ast_log(LOG_NOTICE, "%d messages arrived while mailbox was open\n", last_msg_index - vms->lastmsg); - } - + /* must check up to last detected message, just in case it is erroneously greater than maxmsg */ - for (x = 0; x < last_msg_index + 1; x++) { + for (x = 0; x < vms->lastmsg + 1; x++) { if (!vms->deleted[x] && (strcasecmp(vms->curbox, "INBOX") || !vms->heard[x])) { /* Save this message. It's not in INBOX or hasn't been heard */ make_file(vms->fn, sizeof(vms->fn), vms->curdir, x);