Index: gnome-keyring-ask.c
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring-ask.c,v
retrieving revision 1.16
diff -u -r1.16 gnome-keyring-ask.c
--- gnome-keyring-ask.c	3 Apr 2006 17:30:57 -0000	1.16
+++ gnome-keyring-ask.c	10 Apr 2006 23:21:13 -0000
@@ -79,7 +79,9 @@
 	    const char *secondary,
 	    gboolean include_password,
 	    gboolean include_confirm,
+	    gboolean include_original,
 	    char **password_out,
+	    char **original_out,
 	    guint default_response,
 	    const gchar *first_button_text,
 	    ...)
@@ -89,8 +91,10 @@
 	GtkLabel *notice;
 	char *message;
 	char *notice_text;
+	GtkWidget *old;
 	GtkWidget *entry;
 	GtkWidget *confirm;
+	GtkWidget *label_old;
 	GtkWidget *label_entry;
 	GtkWidget *label_confirm;
 	gint response;
@@ -101,6 +105,7 @@
 	GtkWidget *image;
 	const char *password;
 	const char *confirmation;
+	const char *original;
 
 	dialog = gtk_dialog_new_with_buttons (title , NULL, 0, NULL, NULL);
 	gtk_window_set_icon_name(GTK_WINDOW(dialog), "stock_lock");
@@ -160,6 +165,26 @@
 			    GTK_WIDGET (notice),
 			    0, 2, 1, 2);
 
+	old = NULL;
+	if (include_original) {
+		label_old = gtk_label_new_with_mnemonic (_("_Old password:"));
+		old = gtk_entry_new ();
+		gtk_entry_set_visibility (GTK_ENTRY (old), FALSE);
+		gtk_label_set_mnemonic_widget (GTK_LABEL (label_old), 
+					       old);
+		g_signal_connect_swapped (old,
+					  "activate",
+					  G_CALLBACK (gtk_window_activate_default),
+					  dialog);
+		gtk_table_attach_defaults (GTK_TABLE (table), 
+					   label_old,
+					   0, 1, 2, 3);
+		gtk_misc_set_alignment (GTK_MISC (label_old), 0.0, 0.5);
+		gtk_table_attach_defaults (GTK_TABLE (table), 
+				    old,
+				    1, 2, 2, 3);
+	}
+	
 	entry = NULL;
 	if (include_password) {
 		label_entry = gtk_label_new_with_mnemonic (_("_Password:"));
@@ -173,17 +198,17 @@
 					  dialog);
 		gtk_table_attach_defaults (GTK_TABLE (table), 
 					   label_entry,
-					   0, 1, 2, 3);
+					   0, 1, 3, 4);
 		gtk_misc_set_alignment (GTK_MISC (label_entry), 0.0, 0.5);
 		gtk_table_attach_defaults (GTK_TABLE (table), 
 				    entry,
-				    1, 2, 2, 3);
+				    1, 2, 3, 4);
 	}
 
 	confirm = NULL;
 	if (include_confirm) {
 		gtk_table_resize (GTK_TABLE (table),4,2);
-		label_confirm = gtk_label_new_with_mnemonic (_("_Confirm password:"));
+		label_confirm = gtk_label_new_with_mnemonic (_("_Confirm new password:"));
 		confirm = gtk_entry_new ();
 		gtk_entry_set_visibility (GTK_ENTRY (confirm), FALSE);
 		gtk_label_set_mnemonic_widget (GTK_LABEL (label_confirm), confirm);
@@ -193,16 +218,27 @@
 					  dialog);
 		gtk_table_attach_defaults (GTK_TABLE (table), 
 				    label_confirm,
-				    0, 1, 3, 4);
+				    0, 1, 4, 5);
 		gtk_misc_set_alignment (GTK_MISC (label_confirm), 0.0, 0.5);
 		gtk_table_attach_defaults (GTK_TABLE (table), 
 				    confirm,
-				    1, 2, 3, 4);
+				    1, 2, 4, 5);
 	}
 
  retry:
 	gtk_widget_show_all (dialog);
 	response = gtk_dialog_run (GTK_DIALOG (dialog));
+	
+	if (include_original && old !=NULL && response == GTK_RESPONSE_OK) {
+		original = gtk_entry_get_text (GTK_ENTRY (old));
+		if (*original == 0) {
+			notice_text = create_notice (_("Old password cannot be blank."));
+			gtk_label_set_markup (notice,  notice_text);
+			g_free (notice_text);			
+			goto retry;
+		}
+		*original_out = g_strdup (original);
+	}
 
 	if (include_password && entry != NULL && response == GTK_RESPONSE_OK) {
 		password = gtk_entry_get_text (GTK_ENTRY (entry));
@@ -344,7 +380,7 @@
 	response = run_dialog (_("Unlock Keyring"),
 			       primary,
 			       message,
-			       TRUE, FALSE, &password,
+			       TRUE, FALSE, FALSE, &password, NULL,
 			       GTK_RESPONSE_OK,
 			       _("_Deny"), GTK_RESPONSE_CANCEL,
 			       GTK_STOCK_OK, GTK_RESPONSE_OK,
@@ -428,7 +464,7 @@
 	response = run_dialog (_("New Keyring Password"),
 			       _("Choose password for new keyring"),
 			       message,
-			       TRUE, TRUE, &password,
+			       TRUE, TRUE, FALSE, &password, NULL,
 			       GTK_RESPONSE_OK,
 			       _("_Deny"), GTK_RESPONSE_CANCEL,
 			       GTK_STOCK_OK, GTK_RESPONSE_OK,
@@ -449,6 +485,103 @@
 }
 
 static void
+ask_for_change_keyring_password (gboolean need_original)
+{
+	char *message;
+	char *title;
+	gint response;
+	int app;
+	int keyring;
+	char *password;
+	char *original;
+	
+	app = get_app_information ();
+	if (env_keyring_name == NULL) {
+		env_keyring_name = "";
+	}
+	keyring = get_keyring_information ();
+	g_assert (keyring != KEYRING_NAME_UNKNOWN);
+	
+	message = NULL;
+	if (app == APPLICATION_NAME_DISPLAY_AND_PATH) {
+		if (keyring == KEYRING_NAME_NORMAL) {
+			message = g_strdup_printf (_("The application '%s' (%s) wants to change the password for the '%s' keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_display_name, env_app_pathname, env_keyring_name);
+		} else if (keyring == KEYRING_NAME_DEFAULT) {
+			message = g_strdup_printf (_("The application '%s' (%s) wants to change the password for the default keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_display_name, env_app_pathname);
+		} 
+	} else if (app == APPLICATION_NAME_DISPLAY_ONLY) {
+		if (keyring == KEYRING_NAME_NORMAL) {
+			message = g_strdup_printf (_("The application '%s' wants to change the password for the '%s' keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_display_name, env_keyring_name);
+		} else if (keyring == KEYRING_NAME_DEFAULT) {
+			message = g_strdup_printf (_("The application '%s' wants to change the password for the default keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_display_name);
+		} 
+	} else if (app == APPLICATION_NAME_PATH_ONLY) {
+		if (keyring == KEYRING_NAME_NORMAL) {
+			message = g_strdup_printf (_("The application '%s' wants to change the password for the '%s' keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_pathname, env_keyring_name);
+		} else if (keyring == KEYRING_NAME_DEFAULT) {
+			message = g_strdup_printf (_("The application '%s' wants to change the password for the default keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_app_pathname);
+		} 
+	} else /* app == APPLICATION_NAME_UNKNOWN */ {
+		if (keyring == KEYRING_NAME_NORMAL) {
+			message = g_strdup_printf (_("An unkown application wants to change the password for the '%s' keyring. "
+						     "You have to choose the password you want to use for it."),
+						   env_keyring_name);
+		} else if (keyring == KEYRING_NAME_DEFAULT) {
+			message = g_strdup_printf (_("An unkown application wants to change the password for the default keyring. "
+						     "You have to choose the password you want to use for it."));
+		} 
+	}
+	
+	title = NULL;
+	if (keyring == KEYRING_NAME_NORMAL) {
+		title = g_strdup_printf (_("Choose a new password for the '%s' keyring. "), env_keyring_name);
+	} else if (keyring == KEYRING_NAME_DEFAULT) {
+		title = g_strdup_printf (_("Choose a new password for the default keyring. "));
+	}
+
+	original = NULL;	
+	password = NULL;	
+	response = run_dialog (_("Change Keyring Password"),
+			       _(title),
+			       message,
+			       TRUE, TRUE, need_original, &password, &original,
+			       GTK_RESPONSE_OK,
+			       _("_Deny"), GTK_RESPONSE_CANCEL,
+			       GTK_STOCK_OK, GTK_RESPONSE_OK,
+			       NULL);
+	g_free (message);
+	
+	if (response == GTK_RESPONSE_OK) {
+		response = GNOME_KEYRING_ASK_RESPONSE_ALLOW_ONCE;
+	} else {
+		response = GNOME_KEYRING_ASK_RESPONSE_DENY;
+	}
+	
+	if (password && original) {
+		printf ("%d\n%s\n%s\n", response, original, password);
+		g_free (original);
+		g_free (password);
+	} else if (password) {
+		printf ("%d\n%s\n", response, password);
+		g_free (password);
+	} else {
+		printf ("%d\n\n", response);
+	}
+}
+
+static void
 ask_for_default_keyring (void)
 {
 	char *message;
@@ -479,7 +612,7 @@
 	response = run_dialog (_("Create Default Keyring"),
 			       _("Choose password for default keyring"),
 			       message,
-			       TRUE, TRUE, &password,
+			       TRUE, TRUE, FALSE, &password, NULL,
 			       GTK_RESPONSE_OK,
 			       _("_Deny"), GTK_RESPONSE_CANCEL,
 			       GTK_STOCK_OK, GTK_RESPONSE_OK,
@@ -566,7 +699,7 @@
 
 	response = run_dialog (_("Allow access"),
 			       primary, secondary,
-			       FALSE, FALSE, NULL,
+			       FALSE, FALSE, FALSE, NULL, NULL,
 			       2,
 			       _("_Deny"), GTK_RESPONSE_CANCEL,
 			       _("Allow _Once"), 1,
@@ -618,6 +751,10 @@
 		ask_for_keyring_password ();
 	} else if (strcmp (argv[1], "-n") == 0) {
 		ask_for_new_keyring_password ();
+	} else if (strcmp (argv[1], "-c") == 0) {
+		ask_for_change_keyring_password (FALSE);
+	} else if (strcmp (argv[1], "-o") == 0) {
+		ask_for_change_keyring_password (TRUE);
 	} else if (strcmp (argv[1], "-i") == 0) {
 		ask_for_item_read_write_acccess ();
 	} else if (strcmp (argv[1], "-d") == 0) {
Index: gnome-keyring-daemon.c
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring-daemon.c,v
retrieving revision 1.28
diff -u -r1.28 gnome-keyring-daemon.c
--- gnome-keyring-daemon.c	4 Apr 2006 04:03:07 -0000	1.28
+++ gnome-keyring-daemon.c	10 Apr 2006 23:21:14 -0000
@@ -50,6 +50,8 @@
 	ASK_KEYRING_PASSWORD,
 	ASK_ITEM_READ_WRITE_ACCESS,
 	ASK_NEW_KEYRING_PASSWORD,
+	ASK_ORIGINAL_CHANGE_KEYRING_PASSWORD,
+	ASK_CHANGE_KEYRING_PASSWORD,
 	ASK_DEFAULT_KEYRING
 };
 
@@ -568,6 +570,22 @@
 }
 
 static GnomeKeyringAccessRequest *
+access_request_for_change_keyring_password (const char *keyring_name,
+																			   gboolean need_original)
+{
+	GnomeKeyringAccessRequest *access_request;
+	access_request = g_new0 (GnomeKeyringAccessRequest, 1);
+	if (need_original)
+	{
+		access_request->request_type = GNOME_KEYRING_ACCESS_REQUEST_ORIGINAL_CHANGE_KEYRING_PASSWORD;
+	} else {
+		access_request->request_type = GNOME_KEYRING_ACCESS_REQUEST_CHANGE_KEYRING_PASSWORD;
+	}
+	access_request->new_keyring = g_strdup (keyring_name);
+	return access_request;
+}
+
+static GnomeKeyringAccessRequest *
 access_request_default_keyring (void)
 {
 	GnomeKeyringAccessRequest *access_request;
@@ -616,6 +634,19 @@
 	return find_item_in_list (keyring->items, id);
 }
 
+
+static GnomeKeyringResult
+change_keyring_password ( GnomeKeyring *keyring,  const char *password)
+{
+	if (keyring->locked) {
+		return GNOME_KEYRING_RESULT_DENIED;
+	} else { 
+		keyring->password = g_strdup (password);
+		save_keyring_to_disk (keyring);
+		return GNOME_KEYRING_RESULT_OK;
+	}
+}
+
 static GnomeKeyringResult
 unlock_keyring (GnomeKeyring *keyring, const char *password)
 {
@@ -928,6 +959,7 @@
 
 }
 
+
 static gboolean
 op_create_keyring_execute (GString *packet,
 			   GString *result,
@@ -1053,6 +1085,131 @@
 	return TRUE;
 }
 
+static gboolean
+op_change_keyring_password_collect (GString *packet,
+			   GList **access_requests_out)
+{
+	GList *access_requests;
+	GnomeKeyringOpCode opcode;
+	char *keyring_name, *original, *password;
+	GnomeKeyring *keyring;
+	
+	if (!gnome_keyring_proto_decode_op_string_string_string (packet,
+							  &opcode,
+							  &keyring_name,
+							  &original,
+							  &password)) {
+		return FALSE;
+	}
+
+	access_requests = NULL;
+	
+	if (keyring_name == NULL) {
+		keyring_name = "default_keyring";
+	}
+	
+	keyring = find_keyring (keyring_name);
+	if (keyring == NULL) {
+		/* don't exist */
+		return FALSE;
+	}
+	
+	if (password == NULL) {
+		if (original == NULL ) {
+			/* Prompt for original and Let user pick password */
+			access_requests =
+				g_list_prepend (access_requests,
+						access_request_for_change_keyring_password (keyring_name, TRUE));
+		} else {
+			/* Use original given to us Let user pick password */
+			access_requests =
+				g_list_prepend (access_requests,
+						access_request_for_change_keyring_password (keyring_name, FALSE));
+		}
+	}
+
+// out:
+	*access_requests_out = access_requests;
+	
+	g_free (keyring_name);
+	gnome_keyring_free_password (original);
+	gnome_keyring_free_password (password);
+	
+	return TRUE;
+}
+
+static gboolean
+op_change_keyring_password_execute (GString *packet,
+			   GString *result,
+			   GnomeKeyringApplicationRef *app_ref,
+			   GList *access_requests)
+{
+	char *keyring_name, *original, *password;
+	GnomeKeyring *keyring;
+	GnomeKeyringOpCode opcode;
+	GnomeKeyringAccessRequest *req;
+	
+	if (!gnome_keyring_proto_decode_op_string_string_string (packet,
+							  &opcode,
+							  &keyring_name,
+							  &original,
+							  &password)) {
+		return FALSE;
+	}
+	g_assert (opcode == GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD);
+	
+	if (keyring_name == NULL) {
+		gnome_keyring_proto_add_uint32 (result, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
+		goto out;
+	}
+	
+	keyring = find_keyring (keyring_name);
+	
+	if (keyring == NULL) {
+		gnome_keyring_proto_add_uint32 (result, GNOME_KEYRING_RESULT_DENIED);
+		goto out;
+	}
+	
+	if (original == NULL) {
+		if (access_requests != NULL) {
+			req = access_requests->data;
+			original = g_strdup (req->original);
+		}
+	}
+
+	if (original ==NULL) {
+		gnome_keyring_proto_add_uint32 (result, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
+		goto out;
+	}
+	
+	lock_keyring(keyring);
+	
+	if ( unlock_keyring(keyring, original) != GNOME_KEYRING_RESULT_OK ) {
+		gnome_keyring_proto_add_uint32 (result, GNOME_KEYRING_RESULT_DENIED);
+		goto out;
+	}
+	
+	if (password == NULL) {
+		if (access_requests != NULL) {
+			req = access_requests->data;
+			password = g_strdup (req->password);
+		}
+	}
+	
+	if (password == NULL) {
+		gnome_keyring_proto_add_uint32 (result, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
+		goto out;
+	}
+	
+	gnome_keyring_proto_add_uint32 (result, change_keyring_password (keyring, password));
+	
+ out:
+	g_free (keyring_name);
+	gnome_keyring_free_password (original);
+	gnome_keyring_free_password (password);
+	
+	return TRUE;
+}
 
 static gboolean
 op_list_items_collect (GString *packet,
@@ -2036,6 +2193,7 @@
 	gchar **lines;
 	int response;
 	char *str;
+	char *str1;
 	GnomeKeyring *keyring;
 	GnomeKeyringItem *item;
 
@@ -2045,11 +2203,13 @@
 	/* default for failed requests */
 	response = GNOME_KEYRING_ASK_RESPONSE_FAILURE;
 	str = NULL;
+	str1 = NULL;
 
 	if (!failed) {
 		lines = g_strsplit (ask->buffer->str, "\n", 3);
 		response = atol (lines[0]);
 		str = g_strdup (lines[1]);
+		str1 = g_strdup (lines[2]);
 		g_strfreev (lines);
 	}
 
@@ -2058,7 +2218,6 @@
 			ask->access_requests = g_list_remove (ask->access_requests, ask->current_request);
 			gnome_keyring_access_request_free (ask->current_request);
 	} else {
-		
 		switch (ask->current_ask_type) {
 		case ASK_DEFAULT_KEYRING:
 			if (strlen (str) > 0) {
@@ -2076,6 +2235,19 @@
 				ask->current_request->granted = TRUE;
 			}
 			break;
+		case ASK_ORIGINAL_CHANGE_KEYRING_PASSWORD:
+			if (strlen (str) > 0 && strlen (str1) > 0) {
+				ask->current_request->original = g_strdup (str);
+				ask->current_request->password = g_strdup (str1);
+				ask->current_request->granted = TRUE;
+			}
+			break;
+		case ASK_CHANGE_KEYRING_PASSWORD:
+			if (strlen (str) > 0) {
+				ask->current_request->password = g_strdup (str);
+				ask->current_request->granted = TRUE;
+			}
+			break;
 		case ASK_KEYRING_PASSWORD:
 			if (ask->current_request->keyring != NULL) {
 				keyring = ask->current_request->keyring;
@@ -2196,6 +2368,10 @@
 		argv[1] = "-k";
 	} else if (ask_type == ASK_NEW_KEYRING_PASSWORD) {
 		argv[1] = "-n";
+	} else if (ask_type == ASK_CHANGE_KEYRING_PASSWORD) {
+		argv[1] = "-c";
+	} else if (ask_type == ASK_ORIGINAL_CHANGE_KEYRING_PASSWORD) {
+		argv[1] = "-o";
 	} else if (ask_type == ASK_ITEM_READ_WRITE_ACCESS) {
 		argv[1] = "-i";
 	} else if (ask_type == ASK_DEFAULT_KEYRING) {
@@ -2273,6 +2449,24 @@
 			/* iterate */
 			gnome_keyring_ask_iterate (ask);
 		}
+		break;	
+	case GNOME_KEYRING_ACCESS_REQUEST_ORIGINAL_CHANGE_KEYRING_PASSWORD:
+		if (!launch_ask_helper (ask, ASK_ORIGINAL_CHANGE_KEYRING_PASSWORD)) {
+			/* no way to allow request, denying */
+			ask->access_requests = g_list_remove (ask->access_requests, request);
+			gnome_keyring_access_request_free (request);
+			/* iterate */
+			gnome_keyring_ask_iterate (ask);
+		}
+		break;
+	case GNOME_KEYRING_ACCESS_REQUEST_CHANGE_KEYRING_PASSWORD:
+		if (!launch_ask_helper (ask, ASK_CHANGE_KEYRING_PASSWORD)) {
+			/* no way to allow request, denying */
+			ask->access_requests = g_list_remove (ask->access_requests, request);
+			gnome_keyring_access_request_free (request);
+			/* iterate */
+			gnome_keyring_ask_iterate (ask);
+		}
 		break;
 	case GNOME_KEYRING_ACCESS_REQUEST_DEFAULT_KEYRING:
 		if (!launch_ask_helper (ask, ASK_DEFAULT_KEYRING)) {
@@ -2434,6 +2628,7 @@
 	{ op_set_item_info_or_attributes_collect, op_set_item_attributes_execute}, /* SET_ITEM_ATTRIBUTES */
 	{ op_get_item_info_or_attributes_collect, op_get_item_acl_execute}, /* GET_ITEM_ACL */
 	{ op_set_item_info_or_attributes_collect, op_set_item_acl_execute}, /* SET_ITEM_ACL */
+	{ op_change_keyring_password_collect, op_change_keyring_password_execute }, /*CHANGE_KEYRING_PASSWORD*/
 };
 
 static RETSIGTYPE
Index: gnome-keyring-daemon.h
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring-daemon.h,v
retrieving revision 1.7
diff -u -r1.7 gnome-keyring-daemon.h
--- gnome-keyring-daemon.h	21 Feb 2005 07:53:39 -0000	1.7
+++ gnome-keyring-daemon.h	10 Apr 2006 23:21:15 -0000
@@ -81,6 +81,8 @@
 	GNOME_KEYRING_ACCESS_REQUEST_KEYRING,
 	GNOME_KEYRING_ACCESS_REQUEST_ITEM,
 	GNOME_KEYRING_ACCESS_REQUEST_NEW_KEYRING_PASSWORD,
+	GNOME_KEYRING_ACCESS_REQUEST_ORIGINAL_CHANGE_KEYRING_PASSWORD,
+	GNOME_KEYRING_ACCESS_REQUEST_CHANGE_KEYRING_PASSWORD,
 	GNOME_KEYRING_ACCESS_REQUEST_DEFAULT_KEYRING
 } GnomeKeyringAccessRequestType;
 
@@ -95,6 +97,7 @@
 	
 	char *new_keyring;
 	/* filled out for password requests */
+	char *original;
 	char *password;
 	
 	gboolean granted;
Index: gnome-keyring-proto.c
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring-proto.c,v
retrieving revision 1.9
diff -u -r1.9 gnome-keyring-proto.c
--- gnome-keyring-proto.c	4 May 2005 07:25:14 -0000	1.9
+++ gnome-keyring-proto.c	10 Apr 2006 23:21:16 -0000
@@ -401,6 +401,37 @@
 }
 
 gboolean
+gnome_keyring_proto_encode_op_string_string_string (GString                *buffer,
+					     GnomeKeyringOpCode      op,
+					     const char             *str1,
+					     const char             *str2,
+					     const char             *str3)
+{
+	gsize op_start;
+
+	if (!gnome_keyring_proto_start_operation (buffer, op, &op_start)) {
+		return FALSE;
+	}
+	if (!gnome_keyring_proto_add_utf8_string (buffer,
+						  str1)) {
+		return FALSE;
+	}
+	if (!gnome_keyring_proto_add_utf8_string (buffer,
+						  str2)) {
+		return FALSE;
+	}
+	if (!gnome_keyring_proto_add_utf8_string (buffer,
+						  str3)) {
+		return FALSE;
+	}
+	if (!gnome_keyring_proto_end_operation (buffer,	op_start)) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+gboolean
 gnome_keyring_proto_encode_find (GString *buffer,
 				 GnomeKeyringItemType type,
 				 GnomeKeyringAttributeList *attributes)
@@ -1109,7 +1140,6 @@
 	return FALSE;
 }
 
-
 gboolean
 gnome_keyring_proto_decode_op_string_string (GString *buffer,
 					     GnomeKeyringOpCode *op_out,
@@ -1148,6 +1178,61 @@
 	if (str2 != NULL) {
 		g_free (*str2);
 		*str2 = NULL;
+	}
+	return FALSE;
+}
+
+gboolean
+gnome_keyring_proto_decode_op_string_string_string (GString *buffer,
+					     GnomeKeyringOpCode *op_out,
+					     char **str1,
+					     char **str2,
+					     char **str3)
+{
+	gsize offset;
+
+	if (str1 != NULL) {
+		*str1 = NULL;
+	}
+	if (str2 != NULL) {
+		*str2 = NULL;
+	}
+	if (str3 != NULL) {
+		*str3 = NULL;
+	}
+	if (!gnome_keyring_proto_decode_packet_operation (buffer, op_out)) {
+		return FALSE;
+	}
+	offset = 8;
+	if (!gnome_keyring_proto_get_utf8_string (buffer,
+						  offset, &offset,
+						  str1)) {
+		goto bail;
+	}
+	if (!gnome_keyring_proto_get_utf8_string (buffer,
+						  offset, &offset,
+						  str2)) {
+		goto bail;
+	}
+	if (!gnome_keyring_proto_get_utf8_string (buffer,
+						  offset, &offset,
+						  str3)) {
+		goto bail;
+	}
+	
+	return TRUE;
+ bail:
+	if (str1 != NULL) {
+		g_free (*str1);
+		*str1 = NULL;
+	}
+	if (str2 != NULL) {
+		g_free (*str2);
+		*str2 = NULL;
+	}
+	if (str3 != NULL) {
+		g_free (*str3);
+		*str3 = NULL;
 	}
 	return FALSE;
 }
Index: gnome-keyring-proto.h
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring-proto.h,v
retrieving revision 1.9
diff -u -r1.9 gnome-keyring-proto.h
--- gnome-keyring-proto.h	4 May 2005 07:25:14 -0000	1.9
+++ gnome-keyring-proto.h	10 Apr 2006 23:21:16 -0000
@@ -49,6 +49,7 @@
 	GNOME_KEYRING_OP_SET_ITEM_ACL,
 
 	/* Add new ops here */
+	GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD,
 	
 	GNOME_KEYRING_NUM_OPS
 } GnomeKeyringOpCode;
@@ -110,6 +111,11 @@
 						      GnomeKeyringOpCode         op,
 						      const char                *str1,
 						      const char                *str2);
+gboolean gnome_keyring_proto_encode_op_string_string_string (GString                   *buffer,
+						      GnomeKeyringOpCode         op,
+						      const char                *str1,
+						      const char                *str2,
+						      const char                *str3);
 gboolean gnome_keyring_proto_encode_find             (GString                   *buffer,
 						      GnomeKeyringItemType       type,
 						      GnomeKeyringAttributeList *attributes);
@@ -165,6 +171,11 @@
 							      GnomeKeyringOpCode         *op_out,
 							      char                      **str1_out,
 							      char                      **str2_out);
+gboolean gnome_keyring_proto_decode_op_string_string_string         (GString                    *buffer,
+							      GnomeKeyringOpCode         *op_out,
+							      char                      **str1_out,
+							      char                      **str2_out,
+							      char                      **str3_out);
 gboolean gnome_keyring_proto_decode_op_string_int            (GString                    *buffer,
 							      GnomeKeyringOpCode         *op_out,
 							      char                      **str1,
Index: gnome-keyring.c
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring.c,v
retrieving revision 1.20
diff -u -r1.20 gnome-keyring.c
--- gnome-keyring.c	3 Apr 2006 20:55:09 -0000	1.20
+++ gnome-keyring.c	10 Apr 2006 23:21:17 -0000
@@ -1087,6 +1087,65 @@
         return res;
 }
 
+gpointer
+gnome_keyring_change_password (const char                                  *keyring,
+		      const char                                  *original,
+		      const char                                  *password,
+		      GnomeKeyringOperationDoneCallback            callback,
+		      gpointer                                     data,
+		      GDestroyNotify                               destroy_data)
+{
+	GnomeKeyringOperation *op;
+	
+	op = start_operation (callback, CALLBACK_DONE, data, destroy_data);
+	if (op->state == STATE_FAILED) {
+		return op;
+	}
+	
+	if (!gnome_keyring_proto_encode_op_string_string_string (op->send_buffer,
+							  GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD,
+							  keyring, original, password)) {
+		schedule_op_failed (op, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
+	}
+
+	op->reply_handler = gnome_keyring_standard_reply;
+	
+	return op;
+}
+
+GnomeKeyringResult
+gnome_keyring_change_password_sync (const char *keyring_name,
+			   const char* original, const char *password)
+{
+	GString *send, *receive;
+	GnomeKeyringResult res;
+	
+	send = g_string_new (NULL);
+	
+	if (!gnome_keyring_proto_encode_op_string_string_string (send,
+							  GNOME_KEYRING_OP_CHANGE_KEYRING_PASSWORD,
+							  keyring_name, original, password)) {
+		g_string_free (send, TRUE);
+		return GNOME_KEYRING_RESULT_BAD_ARGUMENTS;
+	}
+	
+ 	receive = g_string_new (NULL);
+	res = run_sync_operation (send, receive);
+	g_string_free (send, TRUE);
+	if (res != GNOME_KEYRING_RESULT_OK) {
+		g_string_free (receive, TRUE);
+		return res;
+	}
+
+	if (!gnome_keyring_proto_decode_result_reply (receive, &res)) {
+		g_string_free (receive, TRUE);
+		return GNOME_KEYRING_RESULT_IO_ERROR;
+	}
+	g_string_free (receive, TRUE);
+
+	return res;
+}
+
 static void
 gnome_keyring_get_keyring_info_reply (GnomeKeyringOperation *op)
 {
Index: gnome-keyring.h
===================================================================
RCS file: /cvs/gnome/gnome-keyring/gnome-keyring.h,v
retrieving revision 1.11
diff -u -r1.11 gnome-keyring.h
--- gnome-keyring.h	27 May 2005 07:55:00 -0000	1.11
+++ gnome-keyring.h	10 Apr 2006 23:21:18 -0000
@@ -175,6 +175,15 @@
 						     gpointer                                      data,
 						     GDestroyNotify                                destroy_data);
 GnomeKeyringResult gnome_keyring_delete_sync        (const char                                   *keyring);
+gpointer           gnome_keyring_change_password             (const char                                   *keyring,
+						     const char                                   *original,
+						     const char                                   *password,
+						     GnomeKeyringOperationDoneCallback             callback,
+						     gpointer                                      data,
+						     GDestroyNotify                                destroy_data);
+GnomeKeyringResult gnome_keyring_change_password_sync        (const char                                   *keyring,
+							 const char								   *original,
+						     const char                                   *password);
 gpointer           gnome_keyring_get_info           (const char                                   *keyring,
 						     GnomeKeyringOperationGetKeyringInfoCallback   callback,
 						     gpointer                                      data,
