Index: modules/ftp-method.c
===================================================================
RCS file: /cvs/gnome/gnome-vfs/modules/ftp-method.c,v
retrieving revision 1.96
diff -u -r1.96 ftp-method.c
--- modules/ftp-method.c	22 Jan 2004 12:29:10 -0000	1.96
+++ modules/ftp-method.c	4 Feb 2004 14:31:23 -0000
@@ -42,6 +42,8 @@
 #include <libgnomevfs/gnome-vfs-module-shared.h>
 #include <libgnomevfs/gnome-vfs-parse-ls.h>
 #include <libgnomevfs/gnome-vfs-utils.h>
+#include <libgnomevfs/gnome-vfs-standard-callbacks.h>
+#include <libgnomevfs/gnome-vfs-module-callback-module-api.h>
 #include <stdio.h> /* for sscanf */
 #include <stdlib.h> /* for atoi */
 #include <string.h>
@@ -81,7 +83,6 @@
 	gchar *dirlist;
 	gchar *dirlistptr;
 	gchar *server_type; /* the response from TYPE */
-	gboolean anonymous;
 	GnomeVFSResult fivefifty; /* the result to return for an FTP 550 */
 	GnomeVFSFileInfoOptions file_info_options;
 } FtpConnection;
@@ -117,8 +118,6 @@
 static void           ftp_connection_release   (FtpConnection *conn);
 
 
-static const char *anon_user = "anonymous";
-static const char *anon_pass = "nobody@gnome.org";
 static const int   control_port = 21;
 
 
@@ -536,34 +535,190 @@
 	return result;
 }
 
+static void save_authn_info (GnomeVFSURI *uri,
+		gchar *user, gchar *pass, gchar *keyring)
+{
+	GnomeVFSModuleCallbackSaveAuthenticationIn in_args;
+        GnomeVFSModuleCallbackSaveAuthenticationOut out_args;
+                                                                                                                                             
+        memset (&in_args, 0, sizeof (in_args));
+        memset (&out_args, 0, sizeof (out_args));
+                                                                                                                                             
+        in_args.keyring = keyring;
+
+	in_args.uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+        in_args.server = (char *)gnome_vfs_uri_get_host_name (uri);
+        in_args.port = gnome_vfs_uri_get_host_port (uri);
+        in_args.username = user;
+        in_args.password = pass;
+        in_args.protocol = "ftp";
+                                                                                                                                             
+        gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_SAVE_AUTHENTICATION,
+                                                &in_args, sizeof (in_args),
+                                                &out_args, sizeof (out_args));
+
+        g_free (in_args.uri);
+}
+
+static gboolean query_user_for_authn_info (GnomeVFSURI *uri, 
+			gchar **user, gchar **pass, gchar **keyring, gboolean *save)
+{
+	GnomeVFSModuleCallbackFullAuthenticationIn in_args;
+        GnomeVFSModuleCallbackFullAuthenticationOut out_args;
+	char *username;
+	gboolean ret;
+
+	ret = FALSE;
+
+	memset (&in_args, 0, sizeof (in_args));
+        memset (&out_args, 0, sizeof (out_args));
+	*user = NULL;
+	*pass = NULL;
+	*keyring = NULL;
+	*save = FALSE;
+
+	in_args.uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+        in_args.server = (char *)gnome_vfs_uri_get_host_name (uri);
+        in_args.port = gnome_vfs_uri_get_host_port (uri);
+        username = (char *)gnome_vfs_uri_get_user_name (uri);
+        if (username != NULL && username[0] != 0) {
+                in_args.username = username;
+        }
+
+	in_args.protocol = "ftp";
+
+	in_args.flags = GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD | GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_SAVING_SUPPORTED;
+        if (in_args.username == NULL) {
+                in_args.flags |= GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME;
+        }
+
+	in_args.default_user = in_args.username;
+
+	ret = gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION,
+                                                &in_args, sizeof (in_args),
+                                                &out_args, sizeof (out_args));
+
+	if (!ret) {
+                goto error;
+        }
+                                                                                                                                             
+        ret = !out_args.abort_auth;
+                                                                                                                                             
+        if (!ret) {
+                goto error;
+        }
+
+	*user = g_strdup (out_args.username);
+	*pass = g_strdup (out_args.password);
+
+	if (out_args.save_password) {
+		*save = TRUE;
+		*keyring = g_strdup (out_args.keyring);
+	}
+
+error:
+      	g_free (in_args.uri);
+       	g_free (in_args.object);
+       	g_free (out_args.username);
+       	g_free (out_args.domain);
+       	g_free (out_args.password);
+       	g_free (out_args.keyring);
+
+	return ret;
+} 
+
+static gboolean query_keyring_for_authn_info (GnomeVFSURI *uri, gchar **user, gchar **pass)
+{
+	GnomeVFSModuleCallbackFillAuthenticationIn in_args;
+        GnomeVFSModuleCallbackFillAuthenticationOut out_args;
+        gboolean ret;
+        char *username;
+                                                                                                                                             
+        ret = FALSE;
+                                                                                                                                             
+        memset (&in_args, 0, sizeof (in_args));
+        memset (&out_args, 0, sizeof (out_args));
+	*user = NULL;
+	*pass = NULL;
+                                                                                                                                             
+        in_args.uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
+        in_args.server = (char *)gnome_vfs_uri_get_host_name (uri);
+        in_args.port = gnome_vfs_uri_get_host_port (uri);
+        username = (char *)gnome_vfs_uri_get_user_name (uri);
+        if (username != NULL && username[0] != 0) {
+                in_args.username = username;
+        }
+        in_args.protocol = "ftp";
+                                                                                                                                             
+        ret = gnome_vfs_module_callback_invoke (GNOME_VFS_MODULE_CALLBACK_FILL_AUTHENTICATION,
+                                                &in_args, sizeof (in_args),
+                                                &out_args, sizeof (out_args));
+
+	if (!ret) {
+                goto error;
+        }
+                                                                                                                                             
+        ret = out_args.valid;
+                                                                                                                                             
+        if (!ret) {
+                goto error;
+        }
+
+        *user = g_strdup (out_args.username);
+        *pass = g_strdup (out_args.password);
+                                                                                                                                             
+error:
+        g_free (in_args.uri);
+        g_free (in_args.object);
+        g_free (out_args.username);
+        g_free (out_args.domain);
+        g_free (out_args.password);
+                                                                                                                                             
+        return ret;
+	
+
+}
+
+static gboolean get_authn_info (GnomeVFSURI *uri, gchar **user, gchar **pass,
+				gchar **keyring, gboolean *save)
+{
+	if (query_keyring_for_authn_info(uri, user, pass)) {
+		return TRUE;
+	}
+
+        return query_user_for_authn_info (uri, user, pass, keyring, save);
+}
 
 static GnomeVFSResult 
 ftp_connection_create (FtpConnection **connptr, GnomeVFSURI *uri, GnomeVFSContext *context) 
 {
 	FtpConnection *conn = g_new0 (FtpConnection, 1);
 	GnomeVFSResult result;
+	gchar *user = NULL;
+	gchar *pass = NULL;
 	gint port = control_port;
-	const gchar *user = anon_user;
-	const gchar *pass = anon_pass;
+	gchar *keyring = NULL;
+	gboolean save_authn = FALSE;
 	
 	conn->uri = gnome_vfs_uri_dup (uri);
 	conn->response_buffer = g_string_new ("");
 	conn->response_code = -1;
-	conn->anonymous = TRUE;
 	conn->fivefifty = GNOME_VFS_ERROR_NOT_FOUND;
 
 	if (gnome_vfs_uri_get_host_port (uri)) {
 		port = gnome_vfs_uri_get_host_port (uri);
 	}
 
-	if (gnome_vfs_uri_get_user_name (uri)) {
-		user = gnome_vfs_uri_get_user_name (uri);
-		conn->anonymous = FALSE;
-	}
-
-	if (gnome_vfs_uri_get_password (uri)) {
-		pass = gnome_vfs_uri_get_password (uri);
-	}
+        if ((gnome_vfs_uri_get_user_name (uri) == NULL) || 
+	    (gnome_vfs_uri_get_password (uri) == NULL)) {
+		if (!get_authn_info (uri, (gchar **)&user, (gchar **)&pass, &keyring, &save_authn)) {
+			return GNOME_VFS_ERROR_ACCESS_DENIED;
+		}
+        }
+	else {
+		user = g_strdup (gnome_vfs_uri_get_user_name (uri));
+		pass = g_strdup (gnome_vfs_uri_get_password (uri));
+	} 
 
 	result = gnome_vfs_inet_connection_create (&conn->inet_connection, 
 						   gnome_vfs_uri_get_host_name (uri), 
@@ -623,6 +778,13 @@
 
 	/* okay, we should be connected now */
 
+	if (save_authn) {
+		save_authn_info (uri, user, pass, keyring);
+	}
+	g_free (user);
+	g_free (pass);
+	g_free (keyring);
+
 	/* Image mode (binary to the uninitiated) */
 
 	do_basic_command (conn, "TYPE I");
