mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-20 11:48:30 -06:00
fix remote login bugs
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@4788 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
78ebc1fd43
commit
3d130fc784
@ -914,7 +914,40 @@ pgendSessionValidate (PGBackend *be, int break_lock)
|
||||
p = "BEGIN;"
|
||||
"LOCK TABLE gncSession IN EXCLUSIVE MODE; ";
|
||||
SEND_QUERY (be,p, FALSE);
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
/* Instead of doing a simple FINISH_QUERY(be->connection);
|
||||
* We need to see if we actually have permission to lock
|
||||
* the table. If its not lockable, then user doesn't have
|
||||
* perms. */
|
||||
retval = TRUE;
|
||||
{
|
||||
int i=0;
|
||||
PGresult *result;
|
||||
do {
|
||||
ExecStatusType status;
|
||||
result = PQgetResult(be->connection);
|
||||
if (!result) break;
|
||||
PINFO ("clearing result %d", i);
|
||||
status = PQresultStatus(result);
|
||||
if (PGRES_COMMAND_OK != status) {
|
||||
PINFO("cannot lock:\n"
|
||||
"\t%s", PQerrorMessage(be->connection));
|
||||
retval = FALSE;
|
||||
}
|
||||
PQclear(result);
|
||||
i++;
|
||||
} while (result);
|
||||
}
|
||||
|
||||
if (FALSE == retval)
|
||||
{
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_PERM);
|
||||
p = "ROLLBACK;";
|
||||
SEND_QUERY (be,p, FALSE);
|
||||
FINISH_QUERY(be->connection);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Check to see if we can start a session of the desired type. */
|
||||
if (FALSE == pgendSessionCanStart (be, break_lock))
|
||||
@ -1170,6 +1203,13 @@ pgend_price_load_single (Backend *bend)
|
||||
* 5) loads data from the database into the engine.
|
||||
*/
|
||||
|
||||
static gpointer
|
||||
db_exists_cb (PGBackend *be, PGresult *result, int j, gpointer data)
|
||||
{
|
||||
return (gpointer) TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
gboolean ignore_lock, gboolean create_new_db)
|
||||
@ -1181,7 +1221,8 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
char *password=NULL;
|
||||
char *pg_options=NULL;
|
||||
char *pg_tty=NULL;
|
||||
char *bufp;
|
||||
char *p;
|
||||
gboolean db_exists = FALSE;
|
||||
|
||||
if (!sess) return;
|
||||
be = (PGBackend *) xaccGNCBookGetBackend (sess);
|
||||
@ -1334,35 +1375,15 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
be->hostname = NULL;
|
||||
}
|
||||
|
||||
#define NEW_LOGIN
|
||||
#ifdef NEW_LOGIN
|
||||
/* not fully implemented */
|
||||
/* Login algorithm. First, we connect to a default, existing
|
||||
* database. (Hopefully it allows any username and password
|
||||
* to connect. We have a problem we don't know how to recover
|
||||
* from if we can't connect to this.) We then query pg_database
|
||||
* to see if the desired dabase exists. (We have a problem if
|
||||
* the dbadmin has set permissions to prevent this query.)
|
||||
* If the user-named db exists, then we connect to it, otherwise
|
||||
* we create it before connecting.
|
||||
/* New login algorithm. If we haven't been told that we'll
|
||||
* need to be creating a database, then lets try to connect,
|
||||
* and see if that succeeds. If it fails, we'll tell gui
|
||||
* to ask user if the DB needs to be created.
|
||||
*/
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
pg_tty, /* file or tty for debug output */
|
||||
"template1",
|
||||
be->username, /* login */
|
||||
password); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
if (FALSE == create_new_db)
|
||||
{
|
||||
PWARN("Can't connect to default database 'template1':\n"
|
||||
"\t%s",
|
||||
PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
|
||||
/* Well, maybe the user-requested database exists, and we
|
||||
* can connect to that ... */
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
@ -1374,37 +1395,208 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PWARN("Connection to database '%s' failed:\n"
|
||||
|
||||
PINFO("Connection to database '%s' failed:\n"
|
||||
"\t%s",
|
||||
be->dbName ? be->dbName : "(null)",
|
||||
PQerrorMessage(be->connection));
|
||||
|
||||
PQfinish (be->connection);
|
||||
|
||||
/* The connection may have failed either because the
|
||||
* database doesn't exist, or because there was a
|
||||
* network problem, or because the user supplied a
|
||||
* bad password or username. Try to tell these apart.
|
||||
*/
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
pg_tty, /* file or tty for debug output */
|
||||
"template1",
|
||||
be->username, /* login */
|
||||
password); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PWARN("Connection to database 'template1' failed:\n"
|
||||
"\t%s",
|
||||
PQerrorMessage(be->connection));
|
||||
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
|
||||
/* I wish that postgres returned usable error codes.
|
||||
* Alas, it does not, so we just bomb out.
|
||||
*/
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_CANT_CONNECT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we are here, then we've successfully connected to the
|
||||
* server. Now, check to see if database exists */
|
||||
p = be->buff; *p = 0;
|
||||
p = stpcpy (p, "SELECT datname FROM pg_database "
|
||||
" WHERE datname='");
|
||||
p = stpcpy (p, be->dbName);
|
||||
p = stpcpy (p, "';");
|
||||
|
||||
SEND_QUERY (be,be->buff, );
|
||||
db_exists = (gboolean) pgendGetResults (be, db_exists_cb, FALSE);
|
||||
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
|
||||
if (db_exists)
|
||||
{
|
||||
/* Weird. We couldn't connect to the database, but it
|
||||
* does seem to exist. I presume that this is some
|
||||
* sort of access control problem. */
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_PERM);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let GUI know that we connected, but we couldn't find it. */
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_NO_SUCH_DB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we are here, then we've been asked to create the
|
||||
* database. Well, lets do that. But first make sure
|
||||
* it really doesn't exist */
|
||||
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
pg_tty, /* file or tty for debug output */
|
||||
"template1",
|
||||
be->username, /* login */
|
||||
password); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PERR("Connection to database '%s' failed:\n"
|
||||
"\t%s",
|
||||
be->dbName ? be->dbName : "(null)",
|
||||
PQerrorMessage(be->connection));
|
||||
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
|
||||
/* OK, this part is convoluted.
|
||||
* I wish that postgres returned usable error codes.
|
||||
/* I wish that postgres returned usable error codes.
|
||||
* Alas, it does not, so we just bomb out.
|
||||
*/
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_CANT_CONNECT);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* If we are here, then we've successfully connected to the
|
||||
* server. Now, check to see if database exists */
|
||||
p = be->buff; *p = 0;
|
||||
p = stpcpy (p, "SELECT datname FROM pg_database "
|
||||
" WHERE datname='");
|
||||
p = stpcpy (p, be->dbName);
|
||||
p = stpcpy (p, "';");
|
||||
|
||||
/* if we are here, then we're connected to 'template1'.
|
||||
* Look for entry in the system table pgdatabase i.e.
|
||||
* SELECT datname FROM pg_database; this should tell us
|
||||
* if it exists already, or if it needs to be created.
|
||||
*/
|
||||
SEND_QUERY (be,be->buff, );
|
||||
db_exists = (gboolean) pgendGetResults (be, db_exists_cb, FALSE);
|
||||
|
||||
if (FALSE == db_exists)
|
||||
{
|
||||
|
||||
PERR ("not implemented");
|
||||
/* create the database */
|
||||
p = be->buff; *p =0;
|
||||
p = stpcpy (p, "CREATE DATABASE ");
|
||||
p = stpcpy (p, be->dbName);
|
||||
p = stpcpy (p, ";");
|
||||
SEND_QUERY (be,be->buff, );
|
||||
FINISH_QUERY(be->connection);
|
||||
PQfinish (be->connection);
|
||||
|
||||
/* now connect to the newly created database */
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
pg_tty, /* file or tty for debug output */
|
||||
be->dbName,
|
||||
be->username, /* login */
|
||||
password); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PERR("Can't connect to the newly created database '%s':\n"
|
||||
"\t%s",
|
||||
be->dbName ? be->dbName : "(null)",
|
||||
PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
/* We just created the database! If we can't connect now,
|
||||
* the server is insane! */
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_SERVER_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finally, create all the tables and indexes.
|
||||
* We do this in pieces, so as not to exceed the max length
|
||||
* for postgres queries (which is 8192).
|
||||
*/
|
||||
SEND_QUERY (be,table_create_str, );
|
||||
FINISH_QUERY(be->connection);
|
||||
SEND_QUERY (be,table_audit_str, );
|
||||
FINISH_QUERY(be->connection);
|
||||
SEND_QUERY (be,sql_functions_str, );
|
||||
FINISH_QUERY(be->connection);
|
||||
be->freshly_created_db = TRUE;
|
||||
be->freshly_created_prdb = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wierd. We were asked to create something that exists.
|
||||
* This shouldn't really happen ... */
|
||||
PWARN ("Asked to create the database %s,\n"
|
||||
"\tbut it already exists!\n"
|
||||
"\tThis shouldn't really happen.",
|
||||
be->dbName);
|
||||
|
||||
PQfinish (be->connection);
|
||||
|
||||
/* Connect to the database */
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
pg_tty, /* file or tty for debug output */
|
||||
be->dbName,
|
||||
be->username, /* login */
|
||||
password); /* pwd */
|
||||
|
||||
/* check the connection status */
|
||||
if (CONNECTION_BAD == PQstatus(be->connection))
|
||||
{
|
||||
PINFO("Can't connect to the database '%s':\n"
|
||||
"\t%s",
|
||||
be->dbName ? be->dbName : "(null)",
|
||||
PQerrorMessage(be->connection));
|
||||
PQfinish (be->connection);
|
||||
be->connection = NULL;
|
||||
|
||||
/* Well, if we are here, we were connecting just fine,
|
||||
* just not to this database. Therefore, it must be a
|
||||
* permission problem.
|
||||
*/
|
||||
xaccBackendSetError (&be->be, ERR_BACKEND_PERM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
/* Old login algorithm. We try to connect to the database that
|
||||
* the user requested. If it fails, we get a fatal message from
|
||||
* postgres. (Porblem: we don't really know why there was a fatal
|
||||
* postgres. (Problem: we don't really know why there was a fatal
|
||||
* error, there may be many reasons. This is the fundamental
|
||||
* problem with this approach.) If the connect failed, then we
|
||||
* create the database, and try again.
|
||||
@ -1455,7 +1647,6 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
|
||||
if (really_do_create)
|
||||
{
|
||||
char * p;
|
||||
be->connection = PQsetdbLogin (be->hostname,
|
||||
be->portno,
|
||||
pg_options, /* trace/debug options */
|
||||
@ -1528,8 +1719,8 @@ pgend_session_begin (GNCBook *sess, const char * sessionid,
|
||||
// DEBUGCMD (PQtrace(be->connection, stderr));
|
||||
|
||||
/* set the datestyle to something we can parse */
|
||||
bufp = "SET DATESTYLE='ISO';";
|
||||
SEND_QUERY (be,bufp, );
|
||||
p = "SET DATESTYLE='ISO';";
|
||||
SEND_QUERY (be,p, );
|
||||
FINISH_QUERY(be->connection);
|
||||
|
||||
/* OK, lets see if we can get a valid session */
|
||||
|
Loading…
Reference in New Issue
Block a user