diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index 783cab69ecf664fdee3f70909a9fd9f166fbb356..940b6ffd534fae1526fe4bf5cff67fec8f5c9f97 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -3779,12 +3779,12 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data) SQLHSTMT stmt; res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); return NULL; } res = SQLPrepare(stmt, (unsigned char *) gps->sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Prepare failed![%s]\n", gps->sql); SQLFreeHandle(SQL_HANDLE_STMT, stmt); return NULL; @@ -3826,14 +3826,14 @@ static void odbc_update_msg_id(char *dir, int msg_num, char *msg_id) * \brief Retrieves a file from an ODBC data store. * \param dir the path to the file to be retrieved. * \param msgnum the message number, such as within a mailbox folder. - * + * * This method is used by the RETRIEVE macro when mailboxes are stored in an ODBC back end. * The purpose is to get the message from the database store to the local file system, so that the message may be played, or the information file may be read. * * The file is looked up by invoking a SQL on the odbc_table (default 'voicemessages') using the dir and msgnum input parameters. * The output is the message information file with the name msgnum and the extension .txt * and the message file with the extension of its format, in the directory with base file name of the msgnum. - * + * * \return 0 on success, -1 on error. */ static int retrieve_file(char *dir, int msgnum) @@ -3846,7 +3846,7 @@ static int retrieve_file(char *dir, int msgnum) SQLSMALLINT colcount = 0; SQLHSTMT stmt; char sql[PATH_MAX]; - char fmt[80]=""; + char fmt[80] = ""; char *c; char coltitle[256]; SQLSMALLINT collen; @@ -3862,144 +3862,139 @@ static int retrieve_file(char *dir, int msgnum) char msgnums[80]; char *argv[] = { dir, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; - struct odbc_obj *obj; + obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - ast_copy_string(fmt, vmfmts, sizeof(fmt)); - c = strchr(fmt, '|'); - if (c) - *c = '\0'; - if (!strcasecmp(fmt, "wav49")) - 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)); + if (!obj) { + ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); + return -1; + } - /* Create the information file */ - snprintf(full_fn, sizeof(full_fn), "%s.txt", fn); - - if (!(f = fopen(full_fn, "w+"))) { - ast_log(AST_LOG_WARNING, "Failed to open/create '%s'\n", full_fn); - goto yuck; - } - - snprintf(full_fn, sizeof(full_fn), "%s.%s", fn, fmt); - snprintf(sql, sizeof(sql), "SELECT * 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); - ast_odbc_release_obj(obj); - goto yuck; - } - res = SQLFetch(stmt); - if (res == SQL_NO_DATA) { - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + ast_copy_string(fmt, vmfmts, sizeof(fmt)); + c = strchr(fmt, '|'); + if (c) + *c = '\0'; + if (!strcasecmp(fmt, "wav49")) + 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); + + 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); + + 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); + goto bail; + } + + res = SQLFetch(stmt); + if (!SQL_SUCCEEDED(res)) { + if (res != SQL_NO_DATA) { ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; } - 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)); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - res = SQLNumResultCols(stmt, &colcount); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - if (f) - fprintf(f, "[message]\n"); - for (x = 0; x < colcount; x++) { - rowdata[0] = '\0'; - colsize = 0; - collen = sizeof(coltitle); - res = SQLDescribeCol(stmt, x + 1, (unsigned char *) coltitle, sizeof(coltitle), &collen, - &datatype, &colsize, &decimaldigits, &nullable); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - if (!strcasecmp(coltitle, "recording")) { - off_t offset; - 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; - } - /* 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); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } else { - res = SQLGetData(stmt, x + 1, SQL_BINARY, fdm, CHUNKSIZE, NULL); - munmap(fdm, CHUNKSIZE); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - unlink(full_fn); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; - } - } + 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); + goto bail_with_handle; + } + + fprintf(f, "[message]\n"); + for (x = 0; x < colcount; x++) { + rowdata[0] = '\0'; + colsize = 0; + collen = sizeof(coltitle); + res = SQLDescribeCol(stmt, x + 1, (unsigned char *) coltitle, sizeof(coltitle), &collen, + &datatype, &colsize, &decimaldigits, &nullable); + if (!SQL_SUCCEEDED(res)) { + 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; + 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; + } + /* 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; } - if (truncate(full_fn, fdlen) < 0) { - ast_log(LOG_WARNING, "Unable to truncate '%s': %s\n", full_fn, strerror(errno)); + 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; } } - } else { - res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); - if ((res == SQL_NULL_DATA) && (!strcasecmp(coltitle, "msg_id"))) { - char msg_id[MSG_ID_LEN]; - generate_msg_id(msg_id); - snprintf(rowdata, sizeof(rowdata), "%s", msg_id); - odbc_update_msg_id(dir, msgnum, msg_id); - } else if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error! coltitle=%s\n[%s]\n\n", coltitle, sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - goto yuck; + if (truncate(full_fn, fdlen) < 0) { + ast_log(LOG_WARNING, "Unable to truncate '%s': %s\n", full_fn, strerror(errno)); } - if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f) - fprintf(f, "%s=%s\n", coltitle, rowdata); + } + } else { + res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); + if (res == SQL_NULL_DATA && !strcasecmp(coltitle, "msg_id")) { + char msg_id[MSG_ID_LEN]; + generate_msg_id(msg_id); + snprintf(rowdata, sizeof(rowdata), "%s", msg_id); + odbc_update_msg_id(dir, msgnum, msg_id); + } else if (!SQL_SUCCEEDED(res)) { + ast_log(AST_LOG_WARNING, "SQL Get Data error! coltitle=%s\n[%s]\n\n", coltitle, sql); + goto bail_with_handle; + } + if (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir")) { + fprintf(f, "%s=%s\n", coltitle, rowdata); } } - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - } else - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: + } + +bail_with_handle: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + +bail: if (f) fclose(f); if (fd > -1) close(fd); + + ast_odbc_release_obj(obj); + return x - 1; } /*! * \brief Determines the highest message number in use for a given user and mailbox folder. - * \param vmu + * \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. @@ -4010,58 +4005,61 @@ yuck: */ static int last_message_index(struct ast_vm_user *vmu, char *dir) { - int x = 0; + int x = -1; 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 msgnum FROM %s WHERE dir=? order by msgnum desc", odbc_table); + if (!obj) { + ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); + return -1; + } - 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_odbc_release_obj(obj); - goto yuck; + 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); + goto bail; + } + + 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); + } else { + ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - if (res == SQL_NO_DATA) { - ast_log(AST_LOG_DEBUG, "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); - } + goto bail_with_handle; + } - 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(AST_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(AST_LOG_WARNING, "Failed to read message index!\n"); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - return x; - } else - ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: - return x - 1; + 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); + goto bail_with_handle; + } + + if (sscanf(rowdata, "%30d", &x) != 1) { + ast_log(AST_LOG_WARNING, "Failed to read message index!\n"); + } + +bail_with_handle: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + +bail: + ast_odbc_release_obj(obj); + + return x; } /*! * \brief Determines if the specified message exists. - * \param dir the folder the mailbox folder to look for messages. + * \param dir the folder the mailbox folder to look for messages. * \param msgnum the message index to query for. * * This method is used when mailboxes are stored in an ODBC back end. @@ -4078,39 +4076,43 @@ static int message_exists(char *dir, int msgnum) char msgnums[20]; char *argv[] = { dir, msgnums }; struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; - struct odbc_obj *obj; + obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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); - ast_odbc_release_obj(obj); - goto yuck; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_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(AST_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(AST_LOG_WARNING, "Failed to read message count!\n"); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: + return 0; + } + + 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); + goto bail; + } + + res = SQLFetch(stmt); + if (!SQL_SUCCEEDED(res)) { + ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", 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); + goto bail_with_handle; + } + + if (sscanf(rowdata, "%30d", &x) != 1) { + ast_log(AST_LOG_WARNING, "Failed to read message count!\n"); + } + +bail_with_handle: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + +bail: + ast_odbc_release_obj(obj); return x; } @@ -4125,48 +4127,50 @@ yuck: */ static int count_messages(struct ast_vm_user *vmu, char *dir) { - int x = 0; + int x = -1; 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(AST_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(AST_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(AST_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(AST_LOG_WARNING, "Failed to read message count!\n"); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - return x; - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); -yuck: - return x - 1; + return -1; + } + + 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); + goto bail; + } + + res = SQLFetch(stmt); + if (!SQL_SUCCEEDED(res)) { + ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", 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); + goto bail_with_handle; + } + + if (sscanf(rowdata, "%30d", &x) != 1) { + ast_log(AST_LOG_WARNING, "Failed to read message count!\n"); + } +bail_with_handle: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + +bail: + ast_odbc_release_obj(obj); + return x; } /*! @@ -4176,7 +4180,7 @@ yuck: * * This method is used when mailboxes are stored in an ODBC back end. * The specified message is directly deleted from the database 'voicemessages' table. - * + * * \return the value greater than zero on success to indicate the number of messages, less than zero on error. */ static void delete_file(const char *sdir, int smsg) @@ -4188,21 +4192,25 @@ static void delete_file(const char *sdir, int smsg) struct generic_prepare_struct gps = { .sql = sql, .argc = 2, .argv = argv }; struct odbc_obj *obj; - argv[0] = ast_strdupa(sdir); - obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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); - else - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + return; + } + + 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); + } else { + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + } + ast_odbc_release_obj(obj); + + return; } /*! @@ -4230,19 +4238,22 @@ static void copy_file(char *sdir, int smsg, char *ddir, int dmsg, char *dmailbox generate_msg_id(msg_id); delete_file(ddir, dmsg); obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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); - else - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - ast_odbc_release_obj(obj); - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + return; + } + + 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); + else + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + ast_odbc_release_obj(obj); + + return; } struct insert_data { @@ -4271,9 +4282,8 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) SQLHSTMT stmt; res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Alloc Handle failed!\n"); - SQLFreeHandle(SQL_HANDLE_STMT, stmt); return NULL; } @@ -4293,7 +4303,7 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) SQLBindParameter(stmt, 13, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(data->category), 0, (void *) data->category, 0, NULL); } res = SQLExecDirect(stmt, (unsigned char *) data->sql, SQL_NTS); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { + if (!SQL_SUCCEEDED(res)) { ast_log(AST_LOG_WARNING, "SQL Direct Execute failed!\n"); SQLFreeHandle(SQL_HANDLE_STMT, stmt); return NULL; @@ -4310,7 +4320,7 @@ static SQLHSTMT insert_data_cb(struct odbc_obj *obj, void *vdata) * \param msgnum the message index for the message to be stored. * * This method is used when mailboxes are stored in an ODBC back end. - * The message sound file and information file is looked up on the file system. + * The message sound file and information file is looked up on the file system. * A SQL query is invoked to store the message into the (MySQL) database. * * \return the zero on success -1 on error. @@ -4335,7 +4345,9 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE }; delete_file(dir, msgnum); - if (!(obj = ast_odbc_request_obj(odbc_database, 0))) { + + 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; } @@ -4398,25 +4410,25 @@ static int store_file(const char *dir, const char *mailboxuser, const char *mail 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); + 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 ((stmt = ast_odbc_direct_execute(obj, insert_data_cb, &idata))) { - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); } else { ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); res = -1; } } while (0); - if (obj) { - ast_odbc_release_obj(obj); - } + + ast_odbc_release_obj(obj); + if (valid_config(cfg)) ast_config_destroy(cfg); if (fdm != MAP_FAILED) @@ -4450,20 +4462,23 @@ static void rename_file(char *sdir, int smsg, char *mailboxuser, char *mailboxco struct generic_prepare_struct gps = { .sql = sql, .argc = 6, .argv = argv }; delete_file(ddir, dmsg); + obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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); - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); - return; + return; + } + + 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; } /*! @@ -5663,17 +5678,48 @@ static void free_zone(struct vm_zone *z) } #ifdef ODBC_STORAGE -static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) + +static int count_messages_in_folder(struct odbc_obj *odbc, const char *context, const char *mailbox, const char *folder, int *messages) { - int x = -1; int res; - SQLHSTMT stmt = NULL; char sql[PATH_MAX]; char rowdata[20]; + SQLHSTMT stmt = NULL; + struct generic_prepare_struct gps = { .sql = sql, .argc = 0 }; + + if (!messages) { + return 0; + } + + snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", 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; + } + 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; + } + 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; + } + + *messages = atoi(rowdata); + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + return 0; +} + +static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) +{ char tmp[PATH_MAX] = ""; - struct odbc_obj *obj = NULL; + struct odbc_obj *obj; char *context; - struct generic_prepare_struct gps = { .sql = sql, .argc = 0 }; if (newmsgs) *newmsgs = 0; @@ -5715,87 +5761,28 @@ static int inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int * } else context = "default"; - if ((obj = ast_odbc_request_obj(odbc_database, 0))) { - do { - if (newmsgs) { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "INBOX"); - if (!(stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps))) { - ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); - break; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - break; - } - res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - break; - } - *newmsgs = atoi(rowdata); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - } - - if (oldmsgs) { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "Old"); - if (!(stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps))) { - ast_log(AST_LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); - break; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - break; - } - res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - break; - } - SQLFreeHandle(SQL_HANDLE_STMT, stmt); - *oldmsgs = atoi(rowdata); - } - - if (urgentmsgs) { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, tmp, "Urgent"); - if (!(stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, &gps))) { - ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); - break; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - break; - } - 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); - break; - } - *urgentmsgs = atoi(rowdata); - } - - x = 0; - } while (0); - } else { + 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; } - if (stmt) { - SQLFreeHandle (SQL_HANDLE_STMT, stmt); + if (count_messages_in_folder(obj, context, tmp, "INBOX", newmsgs) + || count_messages_in_folder(obj, context, tmp, "Old", oldmsgs) + || count_messages_in_folder(obj, context, tmp, "Urgent", urgentmsgs)) { + ast_log(AST_LOG_WARNING, "Failed to obtain message count for mailbox %s@%s\n", + tmp, context); } - if (obj) { - ast_odbc_release_obj(obj); - } - return x; + + ast_odbc_release_obj(obj); + return 0; } /*! * \brief Gets the number of messages that exist in a mailbox folder. * \param mailbox_id * \param folder - * + * * This method is used when ODBC backend is used. * \return The number of messages in this mailbox folder (zero or more). */ @@ -5822,37 +5809,39 @@ static int messagecount(const char *mailbox_id, const char *folder) } obj = ast_odbc_request_obj(odbc_database, 0); - if (obj) { - 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); - } else { - snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder); - } - 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); - goto yuck; - } - res = SQLFetch(stmt); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - goto yuck; - } - res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL); - if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { - ast_log(AST_LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - goto yuck; - } - nummsgs = atoi(rowdata); - SQLFreeHandle (SQL_HANDLE_STMT, stmt); - } else + if (!obj) { ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database); + return 0; + } + + 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); + } else { + snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s%s/%s/%s'", odbc_table, VM_SPOOL_DIR, context, mailbox, folder); + } -yuck: - if (obj) - ast_odbc_release_obj(obj); + 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); + goto bail; + } + res = SQLFetch(stmt); + if (!SQL_SUCCEEDED(res)) { + ast_log(AST_LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", 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); + goto bail_with_handle; + } + nummsgs = atoi(rowdata); + +bail_with_handle: + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + +bail: + ast_odbc_release_obj(obj); return nummsgs; }