[libgda/LIBGDA_4.0] Corrections in the Gda-Sql tool regarding username and password
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda/LIBGDA_4.0] Corrections in the Gda-Sql tool regarding username and password
- Date: Mon, 7 Jun 2010 17:18:08 +0000 (UTC)
commit 713b9523252ec5ba404d4a55fd30cb6a9d771806
Author: Vivien Malerba <malerba gnome-db org>
Date: Mon Jun 7 18:37:32 2010 +0200
Corrections in the Gda-Sql tool regarding username and password
- don't display password's characters while they are entered
- automatically detect when username and password are required
- removed the "-p" comand line option
- improved man page
doc/C/gda-sql-manual.xml | 6 +-
tools/gda-sql.1.in | 26 ++++----
tools/gda-sql.c | 173 +++++++++++++++++++++++++++++++++-------------
3 files changed, 141 insertions(+), 64 deletions(-)
---
diff --git a/doc/C/gda-sql-manual.xml b/doc/C/gda-sql-manual.xml
index 98579fc..a75df25 100644
--- a/doc/C/gda-sql-manual.xml
+++ b/doc/C/gda-sql-manual.xml
@@ -54,7 +54,6 @@
<arg>-C <replaceable>command</replaceable></arg>
<arg>-f <replaceable>commands file</replaceable></arg>
<arg>-o <replaceable>output file</replaceable></arg>
- <arg>-p</arg>
<arg>-s<replaceable>port to use to run embedded HTTP server</replaceable></arg>
<arg>-t<replaceable>authentication token required to authenticate clients when running the embedded HTTP server</replaceable></arg>
<arg rep="repeat"><replaceable>connection specification</replaceable></arg>
@@ -96,9 +95,6 @@ MSAccess | Provider for Microsoft Access files | DB_NAME, |
before the tool exits</para></listitem>
<listitem><para>the <option>-o</option> option allows to specify a file to write the
output to</para></listitem>
- <listitem><para>the <option>-p</option> speficies that the tool should not ask for
- passwords when a username has been specified for a connection but no password has
- been specified.</para></listitem>
<listitem><para>the <option>-s</option> requests the embedded HTTP server to be executed, listening on
the port specified.</para></listitem>
<listitem><para>the <option>-t</option> specifies a token string which clients will have to
@@ -111,6 +107,8 @@ MSAccess | Provider for Microsoft Access files | DB_NAME, |
<listitem><para>defined data sources (the ones listed using the <option>-l</option> option)</para></listitem>
<listitem><para>connection strings which have the following format:
"[<provider>://][<username>[:<password>] ]<connection_params>".
+ If a username or password is required, and is not specified either by a DSN's definition or in
+ the connection string, then it will be requested dynamically.
Note that if provided, <username>, <password> and <provider> must be encoded as per RFC 1738</para></listitem>
<listitem><para>for SQLite and MS Access files: the file name</para></listitem>
</itemizedlist>
diff --git a/tools/gda-sql.1.in b/tools/gda-sql.1.in
index 3b59dba..737661a 100644
--- a/tools/gda-sql.1.in
+++ b/tools/gda-sql.1.in
@@ -1,4 +1,4 @@
-.TH gda-sql 1 "January 09 2009" "Version @PACKAGE_VERSION@" "LIBGDA Manual Pages"
+.TH gda-sql 1 "June 03 2010" "Version @PACKAGE_VERSION@" "LIBGDA Manual Pages"
.SH NAME
gda-sql - an SQL console based on Libgda
@@ -6,7 +6,6 @@ gda-sql - an SQL console based on Libgda
.SH SYNOPSIS
.B gda-sql
[\-\-help] [\-v] [\-\-version]
-[\-p] [\-\-no\-password\-ask]
[\-o] [\-\-output\-file \fI<filename>\fP]
[\-C] [\-\-command]
[\-f] [\-\-commands\-file \fI<filename>\fP]
@@ -14,7 +13,8 @@ gda-sql - an SQL console based on Libgda
[\-l] [\-\-list\-dsn]
[\-L] [\-\-list\-providers]
[\-s] [\-\-http\-port \fI<port>\fP]
-[\-t] [\-\-http\-token \fI<token phrase>\fP] ...
+[\-t] [\-\-http\-token \fI<token phrase>\fP]
+[connection's spec] [connection's spec...]
.SH DESCRIPTION
.PP
@@ -25,8 +25,9 @@ query results.
.PP
Several connections can be opened at the same time, allowing you to switch the active connection to any
opened connection. When starting, gda-sql opens a connection for each connection specified on the command
-line (plus optionnally one corresponding to the \fBGDA_SQL_CNC\fP environment variable). The prompt
-indicates the current connection used when executing commands.
+line (plus optionally one corresponding to the \fBGDA_SQL_CNC\fP environment variable). The prompt
+indicates the current connection used when executing commands. See the \fB.c\fP internal command for
+an explanation about the syntax to specify a connection on the command line.
.PP
Alternatively, input can be from a file.
@@ -42,9 +43,6 @@ gda-sql accepts the following options:
.B \-\-help
Show command\-line options.
.TP 8
-.B \-p, \-\-no\-password\-ask
-Don't ask for a password when it is empty.
-.TP 8
.B \-o, \-\-output\-file \fI<filename>\fP
Specifies a file to which outputs are redirected.
.TP 8
@@ -106,11 +104,11 @@ relative to the location of the gda-sql executable file.
.SH FILES
gda-sql stores data source definitions (DSN) in Libgda defined files
-(\fB$HOME\fP/.libgda/config and @gdasysconfdir@/libgda- GDA_ABI_VERSION@/config
+($HOME/.local/share/libgda and @gdasysconfdir@/libgda- GDA_ABI_VERSION@/config
where ${prefix} is typically /usr).
For each connection defined by a DSN, the meta data is stored in a
-\fB$HOME\fP/.libgda/gda-sql-<DSN>.db file.
+$HOME/.local/share/libgda/gda-sql-<DSN>.db file.
.SH SQL commands
@@ -134,12 +132,14 @@ connections). \fB.bind <CNC_NAME> <CNC_NAME1> <CNC_NAME2> [<CNC_NAME> ...]\fP cr
\fI<CNC_NAME>\fP which binds the tables of the \fI<CNC_NAME1>\fP, \fI<CNC_NAME2>\fP and any other
connection specified.
.IP \fB.c\fP
-Opens a connection or sets the current connection.
+Opens a connection or sets the current connection. Username and password can pe specified using
+the \fB<USERNAME>[:<PASSWORD>]@<DSN_NAME>\fP or \fB<USERNAME>[:<PASSWORD>]@<CNC_DEFINITION>\fP syntax,
+and if a username or a password is required but not specified, it will ba asked interactively.
-\fB.c <CNC_NAME> <DSN_NAME> [USER [PASSWORD]]\fP opens a connection internally known as \fI<CNC_NAME>\fP,
+\fB.c <CNC_NAME> <DSN_NAME>\fP opens a connection internally known as \fI<CNC_NAME>\fP,
using the specified DSN.
-\fB.c <CNC_NAME> <CNC_DEFINITION> [USER [PASSWORD]] \fP opens a connection internally known as \fI<CNC_NAME>\fP,
+\fB.c <CNC_NAME> <CNC_DEFINITION>] \fP opens a connection internally known as \fI<CNC_NAME>\fP,
using a connection specified by \fI<CNC_DEFINITION>\fP which is similar to the \fI<DSN_DEFINITION>\fP parameter
of the \fB.lc\fP command.
diff --git a/tools/gda-sql.c b/tools/gda-sql.c
index 4280853..98f3d7f 100644
--- a/tools/gda-sql.c
+++ b/tools/gda-sql.c
@@ -31,6 +31,7 @@
#include "tools-input.h"
#include "command-exec.h"
#include <unistd.h>
+#include <termios.h>
#include <sys/types.h>
#include <libgda/gda-quark-list.h>
#include <libgda/gda-meta-struct.h>
@@ -54,7 +55,6 @@
/* options */
gboolean show_version = FALSE;
-gboolean ask_pass = FALSE;
gchar *single_command = NULL;
gchar *commandsfile = NULL;
@@ -73,8 +73,6 @@ gchar *auth_token = NULL;
static GOptionEntry entries[] = {
{ "version", 'v', 0, G_OPTION_ARG_NONE, &show_version, "Show version information and exit", NULL },
- { "no-password-ask", 'p', 0, G_OPTION_ARG_NONE, &ask_pass, "Don't ask for a password when it is empty", NULL },
-
{ "output-file", 'o', 0, G_OPTION_ARG_STRING, &outfile, "Output file", "output file"},
{ "command", 'C', 0, G_OPTION_ARG_STRING, &single_command, "Run only single command (SQL or internal) and exit", "command" },
{ "commands-file", 'f', 0, G_OPTION_ARG_STRING, &commandsfile, "Execute commands from file, then exit (except if -i specified)", "filename" },
@@ -179,7 +177,6 @@ main (int argc, char *argv[])
data = g_new0 (MainData, 1);
data->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
main_data = data;
- ask_pass = !ask_pass;
/* output file */
if (outfile) {
@@ -1241,6 +1238,10 @@ static gpointer thread_start_update_meta_store (MetaUpdateData *data);
static void thread_ok_cb_update_meta_store (GdaThreader *threader, guint job, MetaUpdateData *data);
static void thread_cancelled_cb_update_meta_store (GdaThreader *threader, guint job, MetaUpdateData *data);
+static gchar* read_hidden_passwd ();
+static void user_password_needed (GdaDsnInfo *info, const gchar *real_provider,
+ gboolean *out_need_username, gboolean *out_need_password);
+
/*
* Open a connection
*/
@@ -1259,6 +1260,7 @@ open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_st
}
GdaDsnInfo *info;
+ gboolean need_user, need_pass;
gchar *user, *pass, *real_cnc, *real_provider, *real_auth_string = NULL;
/* if cnc string is a regular file, then use it with SQLite */
@@ -1287,6 +1289,10 @@ open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_st
gda_connection_string_split (cnc_string, &real_cnc, &real_provider, &user, &pass);
real_cnc_string = g_strdup (cnc_string);
}
+
+ info = gda_config_get_dsn_info (real_cnc);
+ user_password_needed (info, real_provider, &need_user, &need_pass);
+
if (!real_cnc) {
g_free (user);
g_free (pass);
@@ -1297,55 +1303,70 @@ open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_st
return NULL;
}
- if (ask_pass) {
- if (user && !*user) {
- gchar buf[80];
- g_print (_("\tUsername for '%s': "), cnc_name);
- if (scanf ("%80s", buf) == -1) {
- g_free (real_cnc);
- g_free (user);
- g_free (pass);
- g_free (real_provider);
- g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
- _("No username for '%s'"), cnc_string);
- g_free (real_cnc_string);
- return NULL;
- }
+ if (!user && info && info->auth_string) {
+ GdaQuarkList* ql;
+ const gchar *tmp;
+ ql = gda_quark_list_new_from_string (info->auth_string);
+ tmp = gda_quark_list_find (ql, "USERNAME");
+ if (tmp)
+ user = g_strdup (tmp);
+ gda_quark_list_free (ql);
+ }
+ if (need_user && ((user && !*user) || !user)) {
+ gchar buf[80], *ptr;
+ g_print (_("\tUsername for '%s': "), cnc_name);
+ if (! fgets (buf, 80, stdin)) {
+ g_free (real_cnc);
g_free (user);
- user = g_strdup (buf);
+ g_free (pass);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("No username for '%s'"), cnc_string);
+ g_free (real_cnc_string);
+ return NULL;
}
- if (pass && !*pass) {
- gchar buf[80];
- g_print (_("\tPassword for '%s': "), cnc_name);
- if (scanf ("%80s", buf) == -1) {
- g_free (real_cnc);
- g_free (user);
- g_free (pass);
- g_free (real_provider);
- g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
- _("No password for '%s'"), cnc_string);
- g_free (real_cnc_string);
- return NULL;
+ for (ptr = buf; *ptr; ptr++) {
+ if (*ptr == '\n') {
+ *ptr = 0;
+ break;
}
+ }
+ g_free (user);
+ user = g_strdup (buf);
+ }
+ if (need_pass && ((pass && !*pass) || !pass)) {
+ gchar *tmp;
+ g_print (_("\tPassword for '%s': "), cnc_name);
+ tmp = read_hidden_passwd ();
+ g_print ("\n");
+ if (! tmp) {
+ g_free (real_cnc);
+ g_free (user);
g_free (pass);
- pass = g_strdup (buf);
+ g_free (real_provider);
+ g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_DSN_NOT_FOUND_ERROR,
+ _("No password for '%s'"), cnc_string);
+ g_free (real_cnc_string);
+ return NULL;
}
- if (user || pass) {
- gchar *s1;
- s1 = gda_rfc1738_encode (user);
- if (pass) {
- gchar *s2;
- s2 = gda_rfc1738_encode (pass);
- real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
- g_free (s2);
- }
- else
- real_auth_string = g_strdup_printf ("USERNAME=%s", s1);
- g_free (s1);
+ g_free (pass);
+ pass = tmp;
+ }
+
+ if (user || pass) {
+ gchar *s1;
+ s1 = gda_rfc1738_encode (user);
+ if (pass) {
+ gchar *s2;
+ s2 = gda_rfc1738_encode (pass);
+ real_auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
+ g_free (s2);
}
+ else
+ real_auth_string = g_strdup_printf ("USERNAME=%s", s1);
+ g_free (s1);
}
- info = gda_config_get_dsn_info (real_cnc);
if (info && !real_provider)
newcnc = gda_connection_open_from_dsn (real_cnc_string, real_auth_string, 0, error);
else
@@ -1456,6 +1477,64 @@ open_connection (SqlConsole *console, const gchar *cnc_name, const gchar *cnc_st
return cs;
}
+static void
+user_password_needed (GdaDsnInfo *info, const gchar *real_provider,
+ gboolean *out_need_username, gboolean *out_need_password)
+{
+ GdaProviderInfo *pinfo = NULL;
+ if (out_need_username)
+ *out_need_username = FALSE;
+ if (out_need_password)
+ *out_need_password = FALSE;
+
+ if (real_provider)
+ pinfo = gda_config_get_provider_info (real_provider);
+ else if (info)
+ pinfo = gda_config_get_provider_info (info->provider);
+
+ if (pinfo && pinfo->auth_params) {
+ if (out_need_password && gda_set_get_holder (pinfo->auth_params, "PASSWORD"))
+ *out_need_password = TRUE;
+ if (out_need_username && gda_set_get_holder (pinfo->auth_params, "USERNAME"))
+ *out_need_username = TRUE;
+ }
+}
+
+static gchar*
+read_hidden_passwd (void)
+{
+ gchar *p, password [100];
+ int fail;
+ struct termios termio;
+
+ fail = tcgetattr (0, &termio);
+ if (fail)
+ return NULL;
+
+ termio.c_lflag &= ~ECHO;
+ fail = tcsetattr (0, TCSANOW, &termio);
+ if (fail)
+ return NULL;
+
+ p = fgets (password, sizeof (password) - 1, stdin);
+ termio.c_lflag |= ECHO;
+ tcsetattr (0, TCSANOW, &termio);
+
+ if (!p)
+ return NULL;
+
+ for (p = password; *p; p++) {
+ if (*p == '\n') {
+ *p = 0;
+ break;
+ }
+ }
+ p = g_strdup (password);
+ memset (password, 0, sizeof (password));
+
+ return p;
+}
+
static gpointer
thread_start_update_meta_store (MetaUpdateData *data)
{
@@ -1958,8 +2037,8 @@ build_internal_commands_list (void)
/* specific commands */
c = g_new0 (GdaInternalCommand, 1);
c->group = _("General");
- c->name = g_strdup_printf (_("%s [CNC_NAME [DSN [USER [PASSWORD]]]]"), "c");
- c->description = _("Connect to another defined data source (DSN, see \\l)");
+ c->name = g_strdup_printf (_("%s [CNC_NAME [DSN|CONNECTION STRING]]"), "c");
+ c->description = _("Opens a new connection or lists opened connections");
c->args = NULL;
c->command_func = (GdaInternalCommandFunc) extra_command_manage_cnc;
c->user_data = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]