[Asterisk-code-review] app voicemail: Cleanup ODBC connection handling (asterisk[14])

Joshua Colp asteriskteam at digium.com
Fri Jul 7 16:43:37 CDT 2017


Joshua Colp has submitted this change and it was merged. ( https://gerrit.asterisk.org/5949 )

Change subject: app_voicemail: Cleanup ODBC connection handling
......................................................................

app_voicemail: Cleanup ODBC connection handling

The primary focus of this patch is adding a missing call to
ast_odbc_release_obj(), but is also a general cleanup of the ODBC
related code in app_voicemail.

ASTERISK-27093 #close

Change-Id: I8e285142eaeb3146b4287a928276b70db76c902b
---
M apps/app_voicemail.c
1 file changed, 379 insertions(+), 390 deletions(-)

Approvals:
  Joshua Colp: Looks good to me, but someone else must approve; Approved for Submit
  Richard Mudgett: Looks good to me, approved



diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 13ddb13..19a5d31 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -3781,12 +3781,12 @@
 	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;
@@ -3828,14 +3828,14 @@
  * \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)
@@ -3848,7 +3848,7 @@
 	SQLSMALLINT colcount = 0;
 	SQLHSTMT stmt;
 	char sql[PATH_MAX];
-	char fmt[80]="";
+	char fmt[80] = "";
 	char *c;
 	char coltitle[256];
 	SQLSMALLINT collen;
@@ -3864,144 +3864,139 @@
 	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));
 
-		/* 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_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;
-							}
-						}
-					}
-					if (truncate(full_fn, fdlen) < 0) {
-						ast_log(LOG_WARNING, "Unable to truncate '%s': %s\n", full_fn, strerror(errno));
-					}
-				}
-			} 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 (strcasecmp(coltitle, "msgnum") && strcasecmp(coltitle, "dir") && f)
-					fprintf(f, "%s=%s\n", coltitle, rowdata);
-			}
-		}
-		SQLFreeHandle (SQL_HANDLE_STMT, stmt);
-		ast_odbc_release_obj(obj);
-	} 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);
-yuck:
+		return -1;
+	}
+
+	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);
+		}
+		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;
+					}
+					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));
+				}
+			}
+		} 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);
+			}
+		}
+	}
+
+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.
@@ -4012,58 +4007,61 @@
  */
 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);
-
-		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)) {
-			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);
-			}
-
-			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
+	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 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);
+		}
+		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 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.
@@ -4080,39 +4078,43 @@
 	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;
 }
 
@@ -4127,48 +4129,50 @@
  */
 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
-		ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-yuck:
-	return x - 1;
 
+	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;
+	}
+
+	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;
 }
 
 /*!
@@ -4178,7 +4182,7 @@
  *
  * 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)
@@ -4190,21 +4194,25 @@
 	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_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
+		return;
+	}
+
 	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
-		ast_log(AST_LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
-	return;	
+	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;
 }
 
 /*!
@@ -4232,19 +4240,22 @@
 	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 {
@@ -4273,9 +4284,8 @@
 	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;
 	}
 
@@ -4295,7 +4305,7 @@
 		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;
@@ -4312,7 +4322,7 @@
  * \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.
@@ -4337,7 +4347,9 @@
 	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;
 	}
@@ -4400,25 +4412,25 @@
 			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)
@@ -4452,20 +4464,23 @@
 	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;
 }
 
 /*!
@@ -5665,17 +5680,48 @@
 }
 
 #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];
-	char tmp[PATH_MAX] = "";
-	struct odbc_obj *obj = NULL;
-	char *context;
+	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;
+	char *context;
 
 	if (newmsgs)
 		*newmsgs = 0;
@@ -5717,87 +5763,28 @@
 	} 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).
  */
@@ -5824,37 +5811,39 @@
 	}
 
 	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;
+	}
 
-yuck:
-	if (obj)
-		ast_odbc_release_obj(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 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;
 }
 

-- 
To view, visit https://gerrit.asterisk.org/5949
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 14
Gerrit-MessageType: merged
Gerrit-Change-Id: I8e285142eaeb3146b4287a928276b70db76c902b
Gerrit-Change-Number: 5949
Gerrit-PatchSet: 1
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
Gerrit-Reviewer: Jenkins2
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20170707/ea538352/attachment-0001.html>


More information about the asterisk-code-review mailing list