Fix bug 392357: Allow port specification for a database connection. For both mysql and pgsql,

the port number can be specified after the host, separated by a colon.  The URI spec is:

    mysql://hostname[:port]:dbname:username:password

where [:port] indicates that it is optional.


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18271 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Phil Longstaff 2009-08-22 20:17:37 +00:00
parent 5ea1310b7e
commit f4998e9186
3 changed files with 52 additions and 10 deletions

View File

@ -331,9 +331,11 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
GncDbiBackend *be = (GncDbiBackend*)qbe; GncDbiBackend *be = (GncDbiBackend*)qbe;
gchar* dsn = NULL; gchar* dsn = NULL;
gchar* host; gchar* host;
gchar* port = NULL;
gchar* dbname; gchar* dbname;
gchar* username; gchar* username;
gchar* password; gchar* password;
gint portnum;
gint result; gint result;
gboolean success = FALSE; gboolean success = FALSE;
@ -343,17 +345,29 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
ENTER (" "); ENTER (" ");
/* Split the book-id (format host:dbname:username:password) */ /* Split the book-id (format host:dbname:username:password or
host:port:dbname:username:password) */
dsn = g_strdup( book_id ); dsn = g_strdup( book_id );
for( host = dsn; *host != '/'; host++ ) {} for( host = dsn; *host != '/'; host++ ) {}
host += 2; host += 2;
for( dbname = host; *dbname != ':'; dbname++ ) {} for( dbname = host; *dbname != ':'; dbname++ ) {}
*dbname++ = '\0'; *dbname++ = '\0';
if( *dbname >= '0' && *dbname <= '9' ) {
port = dbname;
for( ; *dbname != ':'; dbname++ ) {}
*dbname++ = '\0';
}
for( username = dbname; *username != ':'; username++ ) {} for( username = dbname; *username != ':'; username++ ) {}
*username++ = '\0'; *username++ = '\0';
for( password = username; *password != ':'; password++ ) {} for( password = username; *password != ':'; password++ ) {}
*password++ = '\0'; *password++ = '\0';
if( port != NULL && *port != '\0' ) {
portnum = atoi( port );
} else {
portnum = 0;
}
// Try to connect to the db. If it doesn't exist and the create_if_nonexistent // Try to connect to the db. If it doesn't exist and the create_if_nonexistent
// flag is TRUE, we'll need to connect to the 'mysql' db and execute the // flag is TRUE, we'll need to connect to the 'mysql' db and execute the
// CREATE DATABASE ddl statement there. // CREATE DATABASE ddl statement there.
@ -367,7 +381,7 @@ gnc_dbi_mysql_session_begin( QofBackend* qbe, QofSession *session,
goto exit; goto exit;
} }
dbi_conn_error_handler( be->conn, mysql_error_fn, be ); dbi_conn_error_handler( be->conn, mysql_error_fn, be );
if( !set_standard_connection_options( qbe, be->conn, host, 0, dbname, username, password ) ) { if( !set_standard_connection_options( qbe, be->conn, host, portnum, dbname, username, password ) ) {
goto exit; goto exit;
} }
be->exists = TRUE; be->exists = TRUE;
@ -469,10 +483,12 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
gint result; gint result;
gchar* dsn; gchar* dsn;
gchar* host; gchar* host;
gchar* port = NULL;
gchar* dbname; gchar* dbname;
gchar* username; gchar* username;
gchar* password; gchar* password;
gboolean success; gboolean success;
gint portnum;
g_return_if_fail( qbe != NULL ); g_return_if_fail( qbe != NULL );
g_return_if_fail( session != NULL ); g_return_if_fail( session != NULL );
@ -480,17 +496,29 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
ENTER (" "); ENTER (" ");
/* Split the book-id (format host:dbname:username:password) */ /* Split the book-id (format host:dbname:username:password or
host:port:dbname:username:password) */
dsn = g_strdup( book_id ); dsn = g_strdup( book_id );
for( host = dsn; *host != '/'; host++ ) {} for( host = dsn; *host != '/'; host++ ) {}
host += 2; host += 2;
for( dbname = host; *dbname != ':'; dbname++ ) {} for( dbname = host; *dbname != ':'; dbname++ ) {}
*dbname++ = '\0'; *dbname++ = '\0';
if( *dbname >= '0' && *dbname <= '9' ) {
port = dbname;
for( ; *dbname != ':'; dbname++ ) {}
*dbname++ = '\0';
}
for( username = dbname; *username != ':'; username++ ) {} for( username = dbname; *username != ':'; username++ ) {}
*username++ = '\0'; *username++ = '\0';
for( password = username; *password != ':'; password++ ) {} for( password = username; *password != ':'; password++ ) {}
*password++ = '\0'; *password++ = '\0';
if( port != NULL && *port != '\0' ) {
portnum = atoi( port );
} else {
portnum = PGSQL_DEFAULT_PORT;
}
// Try to connect to the db. If it doesn't exist and the create_if_nonexistent // Try to connect to the db. If it doesn't exist and the create_if_nonexistent
// flag is TRUE, we'll need to connect to the 'postgres' db and execute the // flag is TRUE, we'll need to connect to the 'postgres' db and execute the
// CREATE DATABASE ddl statement there. // CREATE DATABASE ddl statement there.
@ -504,7 +532,7 @@ gnc_dbi_postgres_session_begin( QofBackend *qbe, QofSession *session,
goto exit; goto exit;
} }
dbi_conn_error_handler( be->conn, pgsql_error_fn, be ); dbi_conn_error_handler( be->conn, pgsql_error_fn, be );
if( !set_standard_connection_options( qbe, be->conn, host, PGSQL_DEFAULT_PORT, dbname, username, password ) ) { if( !set_standard_connection_options( qbe, be->conn, host, portnum, dbname, username, password ) ) {
goto exit; goto exit;
} }
be->exists = TRUE; be->exists = TRUE;

View File

@ -1269,24 +1269,27 @@ gnc_main_window_generate_title (GncMainWindow *window)
if (c == ':') num_colons++; if (c == ':') num_colons++;
} }
if (num_colons != 4) { if (num_colons < 4) {
/* The Gnome HIG 2.0 recommends only the file name (no path) be used. (p15) */ /* The Gnome HIG 2.0 recommends only the file name (no path) be used. (p15) */
ptr = g_utf8_strrchr(filename, -1, G_DIR_SEPARATOR); ptr = g_utf8_strrchr(filename, -1, G_DIR_SEPARATOR);
if (ptr != NULL) if (ptr != NULL)
filename = g_strdup(g_utf8_next_char(ptr)); filename = g_strdup(g_utf8_next_char(ptr));
} else { } else {
const gchar* src = filename; const gchar* src = filename;
gboolean has_explicit_port = (num_colons == 5);
filename = g_strdup(filename); filename = g_strdup(filename);
ptr = filename; ptr = filename;
num_colons = 0; num_colons = 0;
/* Loop and copy chars, converting username and password (after 3rd ':') to /* Loop and copy chars, converting username and password (after 3rd ':' (4th if there's
asterisks. */ an explicit port number) to asterisks. */
for( ; *src; src = g_utf8_next_char(src)) { for( ; *src; src = g_utf8_next_char(src)) {
gunichar unichar; gunichar unichar;
if (num_colons < 3 || *src == ':') { if (*src == ':' ||
(!has_explicit_port && num_colons < 3) ||
(has_explicit_port && num_colons < 4)) {
unichar = g_utf8_get_char(src); unichar = g_utf8_get_char(src);
} else { } else {
unichar = '*'; unichar = '*';

View File

@ -294,12 +294,23 @@ gnc_history_generate_label (int index, const gchar *filename)
if (g_ascii_strncasecmp(filename, "mysql://", 8) == 0 || if (g_ascii_strncasecmp(filename, "mysql://", 8) == 0 ||
g_ascii_strncasecmp(filename, "postgres://", 11) == 0 ) { g_ascii_strncasecmp(filename, "postgres://", 11) == 0 ) {
gint num_colons = 0; gint num_colons = 0;
gboolean has_explicit_port;
/* Count the number of colons to see if there is an explicit port number or not */
for (src = filename; *src; src = g_utf8_next_char(src)) {
gunichar c = g_utf8_get_char(src);
if (c == ':') num_colons++;
}
has_explicit_port = (num_colons == 5);
num_colons = 0;
/* Loop for all chars and copy from 'src' to 'dst'. While doing this, /* Loop for all chars and copy from 'src' to 'dst'. While doing this,
convert username and password (after 3rd ':') to asterisks. */ convert username and password (after 2nd ':', 3rd if explicit port) to asterisks. */
src = filename; src = filename;
for( ; *src; src = g_utf8_next_char(src)) { for( ; *src; src = g_utf8_next_char(src)) {
if (num_colons < 3 || *src == ':') { if (*src == ':' ||
(!has_explicit_port && num_colons < 3) ||
(has_explicit_port && num_colons < 4)) {
unichar = g_utf8_get_char(src); unichar = g_utf8_get_char(src);
} else { } else {
unichar = '*'; unichar = '*';