changeset 4333:cc2f780c0505

[gaim-migrate @ 4597] I needed to make gc->login_time set before do_proto_menu was called, so I moved that line into account_online instead of serv_finish_login. serv_finish_login is called directly after account_online, and gc->login_time isn't used for anything anyway, so it shouldn't matter. I use gc->login_time to determine if a gc's protocol actions menu is ready to be drawn or not (should not be draw for accounts that are in the process of signing online). I made the "Show Buddies Awaiting Authorization" thing show something reasonable for when you aren't waiting for authorization from anyone. I swapped the ok and cancel buttons for the search for buddy by information and clear log file so they follow the HIG. I gave the right side of the log viewer a shadowed border. I Robot. I applied a patch from Ryan McCabe that doesn't really do anything for gaim (yet, anyway), but it allows clients using libfaim to call cleansnacs cleanly, which stops a potential build up of SNACs in memory when you don't send an IM for a long period of time. I applied another patch from Mr. McCabe that fixes a potential crash in ssi.c when your buddy list is a few lions short of a pride, if you know what I mean. I re-prettified an authorization dialog or two. The bold stuff and the non-bold stuff got backwardcised somehow. I added support for those messages from the ICQ server. Like the one that tells you not to give your password to anyone when you first signon. committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Sat, 18 Jan 2003 01:58:00 +0000
parents c8f374cadbd9
children fb911dfb76f4
files src/dialogs.c src/multi.c src/multi.h src/protocols/gg/gg.c src/protocols/jabber/jabber.c src/protocols/msn/msn.c src/protocols/oscar/aim.h src/protocols/oscar/aim_internal.h src/protocols/oscar/oscar.c src/protocols/oscar/snac.c src/protocols/oscar/ssi.c src/protocols/toc/toc.c src/protocols/yahoo/yahoo.c src/prpl.c src/prpl.h src/server.c
diffstat 16 files changed, 414 insertions(+), 294 deletions(-) [+]
line wrap: on
line diff
--- a/src/dialogs.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/dialogs.c	Sat Jan 18 01:58:00 2003 +0000
@@ -2771,8 +2771,8 @@
 	b->stateentry = gtk_entry_new();
 	b->countryentry = gtk_entry_new();
 
+	gtk_box_pack_end(GTK_BOX(bbox), ok, FALSE, FALSE, 0);
 	gtk_box_pack_end(GTK_BOX(bbox), cancel, FALSE, FALSE, 0);
-	gtk_box_pack_end(GTK_BOX(bbox), ok, FALSE, FALSE, 0);
 
 	/* Line 1 */
 	label = gtk_label_new(_("First Name"));
@@ -3989,14 +3989,14 @@
 	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0);
 	gtk_widget_show(hbox);
 
-	button = picture_button(window, _("Cancel"), cancel_xpm);
+	button = picture_button(window, _("Okay"), ok_xpm);
+	gtk_object_set_user_data(GTK_OBJECT(button), gtk_object_get_user_data(GTK_OBJECT(w)));
+	g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(do_clear_log_file), name);
 	g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(destroy_dialog), window);
 	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 5);
 	gtk_widget_show(button);
 
-	button = picture_button(window, _("Okay"), ok_xpm);
-	gtk_object_set_user_data(GTK_OBJECT(button), gtk_object_get_user_data(GTK_OBJECT(w)));
-	g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(do_clear_log_file), name);
+	button = picture_button(window, _("Cancel"), cancel_xpm);
 	g_signal_connect(GTK_OBJECT(button), "clicked", G_CALLBACK(destroy_dialog), window);
 	gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 5);
 	gtk_widget_show(button);
@@ -4244,6 +4244,7 @@
 	sw = gtk_scrolled_window_new(NULL, NULL);
 	gtk_container_set_border_width(GTK_CONTAINER(sw), 5);
 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
 	gtk_widget_set_usize(sw, 390, 220);
 	gtk_container_add(GTK_CONTAINER(frame), sw);
 	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
--- a/src/multi.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/multi.c	Sat Jan 18 01:58:00 2003 +0000
@@ -1321,6 +1321,9 @@
 	struct signon_meter *meter = find_signon_meter(gc);
 	GtkTreeIter iter;
 
+	/* Set the time the account came online */
+	time(&gc->login_time);
+
 	/* first we hide the login progress meter */
 	if (meter) {
 		kill_meter(meter);
--- a/src/multi.h	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/multi.h	Sat Jan 18 01:58:00 2003 +0000
@@ -87,6 +87,12 @@
 	int pos;
 };
 
+struct proto_actions_menu {
+	char *label;
+	void (*callback)(struct gaim_connection *);
+	struct gaim_connection *gc;
+};
+
 struct proto_buddy_menu {
 	char *label;
 	void (*callback)(struct gaim_connection *, char *);
--- a/src/protocols/gg/gg.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/gg/gg.c	Sat Jan 18 01:58:00 2003 +0000
@@ -1,6 +1,6 @@
 /*
  * gaim - Gadu-Gadu Protocol Plugin
- * $Id: gg.c 4474 2003-01-07 20:57:48Z thekingant $
+ * $Id: gg.c 4597 2003-01-18 01:58:00Z thekingant $
  *
  * Copyright (C) 2001 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
  * 
@@ -1157,32 +1157,44 @@
 	}                                        
 }
 
-static void agg_do_action(struct gaim_connection *gc, char *action)
-{
-	if (!strcmp(action, _("Directory Search"))) {
-		show_find_info(gc);
-	} else if (!strcmp(action, _("Change Password"))) {
-		show_change_passwd(gc);
-	} else if (!strcmp(action, _("Import Buddy List from Server"))) {
-		import_buddies_server(gc);
-	} else if (!strcmp(action, _("Export Buddy List to Server"))) {
-		export_buddies_server(gc);
-	} else if (!strcmp(action, _("Delete Buddy List from Server"))) {
-	        delete_buddies_server(gc);
-	}
-}
-
-static GList *agg_actions()
+static GList *agg_actions(struct gaim_connection *gc)
 {
 	GList *m = NULL;
+	struct proto_actions_menu *pam;
 
-	m = g_list_append(m, _("Directory Search"));
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Directory Search");
+	pam->callback = show_find_info;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	m = g_list_append(m, NULL);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Change Password");
+	pam->callback = show_change_passwd;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
 	m = g_list_append(m, NULL);
-	m = g_list_append(m, _("Change Password"));
-	m = g_list_append(m, NULL);
-	m = g_list_append(m, _("Import Buddy List from Server"));
-	m = g_list_append(m, _("Export Buddy List to Server"));
-	m = g_list_append(m, _("Delete Buddy List from Server"));
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Import Buddy List from Server");
+	pam->callback = import_buddies_server;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Export Buddy List to Server");
+	pam->callback = export_buddies_server;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Delete Buddy List from Server");
+	pam->callback = delete_buddies_server;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -1258,7 +1270,6 @@
 	ret->list_icon = agg_list_icon;
 	ret->away_states = agg_away_states;
 	ret->actions = agg_actions;
-	ret->do_action = agg_do_action;
 	ret->buddy_menu = agg_buddy_menu;
 	ret->chat_info = NULL;
 	ret->login = agg_login;
--- a/src/protocols/jabber/jabber.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/jabber/jabber.c	Sat Jan 18 01:58:00 2003 +0000
@@ -4147,28 +4147,30 @@
 /* End Jabber "user registration" support */
 /*----------------------------------------*/
 
-static void jabber_do_action(struct gaim_connection *gc, char *act)
-{
-	if (!strcmp(act, _("Set User Info"))) {
-		jabber_setup_set_info(gc);
-	/*
-	} else if (!strcmp(act, _("Set Dir Info"))) {
-		show_set_dir(gc);
-	 */
-	} else if (!strcmp(act, _("Change Password"))) {
-		show_change_passwd(gc);
-	}
-}
-
-static GList *jabber_actions()
+static GList *jabber_actions(struct gaim_connection *gc)
 {
 	GList *m = NULL;
-
-	m = g_list_append(m, _("Set User Info"));
+	struct proto_actions_menu *pam;
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set User Info");
+	pam->callback = jabber_setup_set_info;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
 	/*
-	m = g_list_append(m, _("Set Dir Info"));
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set Dir Info");
+	pam->callback = show_set_dir;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 	 */
-	m = g_list_append(m, _("Change Password"));
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Change Password");
+	pam->callback = show_change_passwd;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -4183,7 +4185,6 @@
 	ret->list_icon = jabber_list_icon;
 	ret->away_states = jabber_away_states;
 	ret->actions = jabber_actions;
-	ret->do_action = jabber_do_action;
 	ret->buddy_menu = jabber_buddy_menu;
 	ret->edit_buddy_menu = jabber_edit_buddy_menu;
 	ret->login = jabber_login;
--- a/src/protocols/msn/msn.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/msn/msn.c	Sat Jan 18 01:58:00 2003 +0000
@@ -2551,18 +2551,21 @@
 	}
 }
 
-static void msn_do_action(struct gaim_connection *gc, char *act)
+static void msn_show_set_friendly_name(struct gaim_connection *gc)
 {
-	if (!strcmp(act, _("Set Friendly Name"))) {
-		do_prompt_dialog(_("Set Friendly Name:"), gc->displayname, gc, msn_act_id, NULL);
-	}
+	do_prompt_dialog(_("Set Friendly Name:"), gc->displayname, gc, msn_act_id, NULL);
 }
 
-static GList *msn_actions()
+static GList *msn_actions(struct gaim_connection *gc)
 {
 	GList *m = NULL;
-
-	m = g_list_append(m, _("Set Friendly Name"));
+	struct proto_actions_menu *pam;
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set Friendly Name");
+	pam->callback = msn_show_set_friendly_name;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -2837,7 +2840,6 @@
 	ret->chat_invite = msn_chat_invite;
 	ret->chat_leave = msn_chat_leave;
 	ret->normalize = msn_normalize;
-	ret->do_action = msn_do_action;
 	ret->actions = msn_actions;
 	ret->convo_closed = msn_convo_closed;
 	ret->keepalive = msn_keepalive;
--- a/src/protocols/oscar/aim.h	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/oscar/aim.h	Sat Jan 18 01:58:00 2003 +0000
@@ -625,6 +625,7 @@
 faim_export int aim_send_login(aim_session_t *, aim_conn_t *, const char *, const char *, struct client_info_s *, const char *key);
 faim_export int aim_encode_password_md5(const char *password, const char *key, unsigned char *digest);
 faim_export void aim_purge_rxqueue(aim_session_t *);
+faim_export void aim_cleansnacs(aim_session_t *, int maxage);
 
 #define AIM_TX_QUEUED    0 /* default */
 #define AIM_TX_IMMEDIATE 1
--- a/src/protocols/oscar/aim_internal.h	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/oscar/aim_internal.h	Sat Jan 18 01:58:00 2003 +0000
@@ -139,7 +139,6 @@
 faim_internal aim_snacid_t aim_newsnac(aim_session_t *, aim_snac_t *newsnac);
 faim_internal aim_snacid_t aim_cachesnac(aim_session_t *sess, const fu16_t family, const fu16_t type, const fu16_t flags, const void *data, const int datalen);
 faim_internal aim_snac_t *aim_remsnac(aim_session_t *, aim_snacid_t id);
-faim_internal void aim_cleansnacs(aim_session_t *, int maxage);
 faim_internal int aim_putsnac(aim_bstream_t *, fu16_t family, fu16_t type, fu16_t flags, aim_snacid_t id);
 
 /* Stored in ->priv of the service request SNAC for chats. */
--- a/src/protocols/oscar/oscar.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/oscar/oscar.c	Sat Jan 18 01:58:00 2003 +0000
@@ -1884,7 +1884,7 @@
 			g_hash_table_insert(od->supports_tn, who, who);
 	}
 
-	//strip_linefeed(tmp);
+	/* strip_linefeed(tmp); */
 	serv_got_im(gc, userinfo->sn, tmp, flags, time(NULL), -1);
 	g_free(tmp);
 
@@ -2232,6 +2232,14 @@
 			g_free(dialog_msg);
 		} break;
 
+		case 0x09: { /* Message from the Godly ICQ server itself, I think */
+			if (i >= 5) {
+				gchar *dialog_msg = g_strdup_printf(_("You have received a special message\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
+				do_error_dialog("ICQ Server Message", dialog_msg, GAIM_INFO);
+				g_free(dialog_msg);
+			}
+		} break;
+
 		case 0x0d: { /* Someone has sent you a pager message from http://www.icq.com/your_uin */
 			if (i >= 6) {
 				gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ page\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
@@ -4901,82 +4909,6 @@
 		oscar_get_info(gc, who);
 }
 
-static GList *oscar_buddy_menu(struct gaim_connection *gc, char *who) {
-	struct oscar_data *od = gc->proto_data;
-	GList *m = NULL;
-	struct proto_buddy_menu *pbm;
-
-	pbm = g_new0(struct proto_buddy_menu, 1);
-	pbm->label = _("Get Info");
-	pbm->callback = oscar_get_info;
-	pbm->gc = gc;
-	m = g_list_append(m, pbm);
-
-	if (od->icq) {
-		pbm = g_new0(struct proto_buddy_menu, 1);
-		pbm->label = _("Get Status Msg");
-		pbm->callback = oscar_get_away_msg;
-		pbm->gc = gc;
-		m = g_list_append(m, pbm);
-	} else {
-		pbm = g_new0(struct proto_buddy_menu, 1);
-		pbm->label = _("Get Away Msg");
-		pbm->callback = oscar_get_away_msg;
-		pbm->gc = gc;
-		m = g_list_append(m, pbm);
-
-		if (aim_sncmp(gc->username, who)) {
-			pbm = g_new0(struct proto_buddy_menu, 1);
-			pbm->label = _("Direct IM");
-			pbm->callback = oscar_ask_direct_im;
-			pbm->gc = gc;
-			m = g_list_append(m, pbm);
-		
-			pbm = g_new0(struct proto_buddy_menu, 1);
-			pbm->label = _("Send File");
-			pbm->callback = oscar_ask_send_file;
-			pbm->gc = gc;
-			m = g_list_append(m, pbm);
-		}
-	}
-
-	pbm = g_new0(struct proto_buddy_menu, 1);
-	pbm->label = _("Get Capabilities");
-	pbm->callback = oscar_get_caps;
-	pbm->gc = gc;
-	m = g_list_append(m, pbm);
-
-	return m;
-}
-
-static GList *oscar_edit_buddy_menu(struct gaim_connection *gc, char *who)
-{
-	struct oscar_data *od = gc->proto_data;
-	GList *m = NULL;
-	struct proto_buddy_menu *pbm;
-
-	if (od->icq) {
-		pbm = g_new0(struct proto_buddy_menu, 1);
-		pbm->label = _("Get Info");
-		pbm->callback = oscar_get_info;
-		pbm->gc = gc;
-		m = g_list_append(m, pbm);
-	}
-
-	if (od->sess->ssi.received_data) {
-		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, who);
-		if (gname && aim_ssi_waitingforauth(od->sess->ssi.local, gname, who)) {
-			pbm = g_new0(struct proto_buddy_menu, 1);
-			pbm->label = _("Re-request Authorization");
-			pbm->callback = gaim_auth_sendrequest;
-			pbm->gc = gc;
-			m = g_list_append(m, pbm);
-		}
-	}
-
-	return m;
-}
-
 static void oscar_set_permit_deny(struct gaim_connection *gc) {
 	struct oscar_data *od = (struct oscar_data *)gc->proto_data;
 #ifdef NOSSI
@@ -5088,17 +5020,140 @@
 	if (!od->icq)
 		return g_list_append(m, GAIM_AWAY_CUSTOM);
 
-	m = g_list_append(m, "Online");
-	m = g_list_append(m, "Away");
-	m = g_list_append(m, "Do Not Disturb");
-	m = g_list_append(m, "Not Available");
-	m = g_list_append(m, "Occupied");
-	m = g_list_append(m, "Free For Chat");
-	m = g_list_append(m, "Invisible");
+	m = g_list_append(m, _("Online"));
+	m = g_list_append(m, _("Away"));
+	m = g_list_append(m, _("Do Not Disturb"));
+	m = g_list_append(m, _("Not Available"));
+	m = g_list_append(m, _("Occupied"));
+	m = g_list_append(m, _("Free For Chat"));
+	m = g_list_append(m, _("Invisible"));
+
+	return m;
+}
+
+static GList *oscar_buddy_menu(struct gaim_connection *gc, char *who) {
+	struct oscar_data *od = gc->proto_data;
+	GList *m = NULL;
+	struct proto_buddy_menu *pbm;
+
+	pbm = g_new0(struct proto_buddy_menu, 1);
+	pbm->label = _("Get Info");
+	pbm->callback = oscar_get_info;
+	pbm->gc = gc;
+	m = g_list_append(m, pbm);
+
+	if (od->icq) {
+		pbm = g_new0(struct proto_buddy_menu, 1);
+		pbm->label = _("Get Status Msg");
+		pbm->callback = oscar_get_away_msg;
+		pbm->gc = gc;
+		m = g_list_append(m, pbm);
+	} else {
+		pbm = g_new0(struct proto_buddy_menu, 1);
+		pbm->label = _("Get Away Msg");
+		pbm->callback = oscar_get_away_msg;
+		pbm->gc = gc;
+		m = g_list_append(m, pbm);
+
+		if (aim_sncmp(gc->username, who)) {
+			pbm = g_new0(struct proto_buddy_menu, 1);
+			pbm->label = _("Direct IM");
+			pbm->callback = oscar_ask_direct_im;
+			pbm->gc = gc;
+			m = g_list_append(m, pbm);
+		
+			pbm = g_new0(struct proto_buddy_menu, 1);
+			pbm->label = _("Send File");
+			pbm->callback = oscar_ask_send_file;
+			pbm->gc = gc;
+			m = g_list_append(m, pbm);
+		}
+	}
+
+	pbm = g_new0(struct proto_buddy_menu, 1);
+	pbm->label = _("Get Capabilities");
+	pbm->callback = oscar_get_caps;
+	pbm->gc = gc;
+	m = g_list_append(m, pbm);
 
 	return m;
 }
 
+static GList *oscar_edit_buddy_menu(struct gaim_connection *gc, char *who)
+{
+	struct oscar_data *od = gc->proto_data;
+	GList *m = NULL;
+	struct proto_buddy_menu *pbm;
+
+	if (od->icq) {
+		pbm = g_new0(struct proto_buddy_menu, 1);
+		pbm->label = _("Get Info");
+		pbm->callback = oscar_get_info;
+		pbm->gc = gc;
+		m = g_list_append(m, pbm);
+	}
+
+	if (od->sess->ssi.received_data) {
+		char *gname = aim_ssi_itemlist_findparentname(od->sess->ssi.local, who);
+		if (gname && aim_ssi_waitingforauth(od->sess->ssi.local, gname, who)) {
+			pbm = g_new0(struct proto_buddy_menu, 1);
+			pbm->label = _("Re-request Authorization");
+			pbm->callback = gaim_auth_sendrequest;
+			pbm->gc = gc;
+			m = g_list_append(m, pbm);
+		}
+	}
+
+	return m;
+}
+
+static void oscar_format_screenname(struct gaim_connection *gc, char *nick) {
+	struct oscar_data *od = gc->proto_data;
+	if (!aim_sncmp(gc->username, nick)) {
+		if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
+			od->setnick = TRUE;
+			od->newsn = g_strdup(nick);
+			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
+		} else {
+			aim_admin_setnick(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), nick);
+		}
+	} else {
+		do_error_dialog(_("The new formatting is invalid."),
+				_("Screenname formatting can change only capitalization and whitespace."), GAIM_ERROR);
+	}
+}
+
+static void oscar_show_format_screenname(struct gaim_connection *gc)
+{
+	do_prompt_dialog(_("New screenname formatting:"), gc->displayname, gc, oscar_format_screenname, NULL);
+}
+
+static void oscar_confirm_account(struct gaim_connection *gc)
+{
+	struct oscar_data *od = gc->proto_data;
+	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
+
+	if (conn) {
+		aim_admin_reqconfirm(od->sess, conn);
+	} else {
+		od->conf = TRUE;
+		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
+	}
+}
+
+static void oscar_show_email(struct gaim_connection *gc)
+{
+	struct oscar_data *od = gc->proto_data;
+	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
+
+	if (conn) {
+		aim_admin_getinfo(od->sess, conn, 0x11);
+	} else {
+		od->reqemail = TRUE;
+		aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
+	}
+}
+
 static void oscar_change_email(struct gaim_connection *gc, char *email)
 {
 	struct oscar_data *od = gc->proto_data;
@@ -5113,96 +5168,131 @@
 	}
 }
 
-static void oscar_format_screenname(struct gaim_connection *gc, char *nick) {
+static void oscar_show_change_email(struct gaim_connection *gc)
+{
+	do_prompt_dialog(_("Change Address To: "), NULL, gc, oscar_change_email, NULL);
+}
+
+static void oscar_show_awaitingauth(struct gaim_connection *gc)
+{
 	struct oscar_data *od = gc->proto_data;
-	if (!aim_sncmp(gc->username, nick)) {
-		if (!aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH)) {
-			od->setnick = TRUE;
-			od->newsn = g_strdup(nick);
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-		} else {
-			aim_admin_setnick(od->sess, aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH), nick);
+	gchar *nombre, *text, *tmp;
+	GSList *curg, *curb;
+	int num=0;
+
+	text = g_strdup(_("You are awaiting authorization from the following buddies:<BR>"));
+
+	for (curg=gc->groups; curg; curg=g_slist_next(curg)) {
+		struct group *group = curg->data;
+		for (curb=group->members; curb; curb=g_slist_next(curb)) {
+			struct buddy *buddy = curb->data;
+			if (aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) {
+				if (get_buddy_alias_only(buddy))
+					nombre = g_strdup_printf(" %s (%s)", buddy->name, get_buddy_alias_only(buddy));
+				else
+					nombre = g_strdup(buddy->name);
+				tmp = g_strdup_printf("%s<BR>%s", text, nombre);
+				g_free(text);
+				text = tmp;
+				g_free(nombre);
+				num++;
+			}
 		}
-	} else {
-		do_error_dialog("The new formatting is invalid.",
-				"Screenname formatting can change only capitalization and whitespace.", GAIM_ERROR);
+	}
+
+	if (!num) {
+		tmp = g_strdup_printf("%s<BR>%s", text, _("<i>you are not waiting for authorization</i>"));
+		g_free(text);
+		text = tmp;
 	}
+
+	tmp = g_strdup_printf(_("%s<BR><BR>You can re-request authorization from these buddies by right-clicking on them in the \"Edit Buddies\" pane and selecting \"Re-request authorization.\""), text);
+	g_free(text);
+	text = tmp;
+	g_show_info_text(gc, gc->username, 2, text, NULL);
+	g_free(text);
 }
 
-static void oscar_do_action(struct gaim_connection *gc, char *act)
+static void oscar_show_chpassurl(struct gaim_connection *gc)
+{
+	struct oscar_data *od = gc->proto_data;
+	open_url(NULL, od->sess->authinfo->chpassurl);
+}
+
+static GList *oscar_actions(struct gaim_connection *gc)
 {
 	struct oscar_data *od = gc->proto_data;
-	aim_conn_t *conn = aim_getconn_type(od->sess, AIM_CONN_TYPE_AUTH);
-
-	if (!strcmp(act, "Set User Info")) {
-		show_set_info(gc);
-	} else if (!strcmp(act, "Change Password")) {
-		show_change_passwd(gc);
-	} else if (!strcmp(act, "Format Screenname")) {
-		do_prompt_dialog("New screenname formatting:", 
-				 gc->displayname, gc, oscar_format_screenname, NULL);
-	} else if (!strcmp(act, "Confirm Account")) {
-		if (!conn) {
-			od->conf = TRUE;
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-		} else
-			aim_admin_reqconfirm(od->sess, conn);
-	} else if (!strcmp(act, "Display Current Registered Address")) {
-		if (!conn) {
-			od->reqemail = TRUE;
-			aim_reqservice(od->sess, od->conn, AIM_CONN_TYPE_AUTH);
-		} else
-			aim_admin_getinfo(od->sess, conn, 0x11);
-	} else if (!strcmp(act, "Change Current Registered Address")) {
-		do_prompt_dialog("Change Address To: ", NULL, gc, oscar_change_email, NULL);
-	} else if (!strcmp(act, "Show Buddies Awaiting Authorization")) {
-		gchar *nombre, *text, *tmp;
-		GSList *curg, *curb;
-
-		text = g_strdup(_("You are awaiting authorization from the following buddies:"));
-
-		for (curg=gc->groups; curg; curg=g_slist_next(curg)) {
-			struct group *group = curg->data;
-			for (curb=group->members; curb; curb=g_slist_next(curb)) {
-				struct buddy *buddy = curb->data;
-				if (aim_ssi_waitingforauth(od->sess->ssi.local, group->name, buddy->name)) {
-					if (get_buddy_alias_only(buddy))
-						nombre = g_strdup_printf(" %s (%s)", buddy->name, get_buddy_alias_only(buddy));
-					else
-						nombre = g_strdup(buddy->name);
-					tmp = g_strdup_printf("%s<BR>%s", text, nombre);
-					g_free(text);
-					text = tmp;
-					g_free(nombre);
-				}
-			}
-		}
-
-		tmp = g_strdup_printf(_("%s<BR><BR>You can re-request authorization from these buddies by right-clicking on them in the \"Edit Buddies\" pane and selecting \"Re-request authorization.\""), text);
-		g_free(text);
-		text = tmp;
-		g_show_info_text(gc, gc->username, 2, text, NULL);
-		g_free(text);
-	} else if (!strcmp(act, "Search for Buddy by Email")) {
-		show_find_email(gc);
+	struct proto_actions_menu *pam;
+	GList *m = NULL;
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set User Info");
+	pam->callback = show_set_info;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	if (od->sess->authinfo->regstatus == 0x0003) {
+		/* AIM actions */
+		m = g_list_append(m, NULL);
+
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Change Password");
+		pam->callback = show_change_passwd;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Format Screenname");
+		pam->callback = oscar_show_format_screenname;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Confirm Account");
+		pam->callback = oscar_confirm_account;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Display Current Registered Address");
+		pam->callback = oscar_show_email;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Change Current Registered Address");
+		pam->callback = oscar_show_change_email;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
+	} else if (od->sess->authinfo->chpassurl) {
+		pam = g_new0(struct proto_actions_menu, 1);
+		pam->label = _("Change Password");
+		pam->callback = oscar_show_chpassurl;
+		pam->gc = gc;
+		m = g_list_append(m, pam);
 	}
-}
-
-static GList *oscar_actions()
-{
-	GList *m = NULL;
-
-	m = g_list_append(m, "Set User Info");
+
+	m = g_list_append(m, NULL);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Show Buddies Awaiting Authorization");
+	pam->callback = oscar_show_awaitingauth;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
 	m = g_list_append(m, NULL);
-	m = g_list_append(m, "Change Password");
-	m = g_list_append(m, "Format Screenname");
-	m = g_list_append(m, "Confirm Account");
-	m = g_list_append(m, "Display Current Registered Address");
-	m = g_list_append(m, "Change Current Registered Address");
-	m = g_list_append(m, NULL);
-	m = g_list_append(m, "Show Buddies Awaiting Authorization");
-	m = g_list_append(m, NULL);
-	m = g_list_append(m, "Search for Buddy by Email");
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Search for Buddy by Email");
+	pam->callback = show_find_email;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Search for Buddy by Information");
+	pam->callback = show_find_info;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -5301,7 +5391,6 @@
 	ret->list_icon = oscar_list_icon;
 	ret->away_states = oscar_away_states;
 	ret->actions = oscar_actions;
-	ret->do_action = oscar_do_action;
 	ret->buddy_menu = oscar_buddy_menu;
 	ret->edit_buddy_menu = oscar_edit_buddy_menu;
 	ret->login = oscar_login;
--- a/src/protocols/oscar/snac.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/oscar/snac.c	Sat Jan 18 01:58:00 2003 +0000
@@ -143,7 +143,7 @@
  * maxage is the _minimum_ age in seconds to keep SNACs.
  *
  */
-faim_internal void aim_cleansnacs(aim_session_t *sess, int maxage)
+faim_export void aim_cleansnacs(aim_session_t *sess, int maxage)
 {
 	int i;
 
--- a/src/protocols/oscar/ssi.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/oscar/ssi.c	Sat Jan 18 01:58:00 2003 +0000
@@ -637,7 +637,7 @@
  */
 faim_export int aim_ssi_cleanlist(aim_session_t *sess, aim_conn_t *conn)
 {
-	struct aim_ssi_item *cur;
+	struct aim_ssi_item *cur, *next;
 
 	/* If there are any buddies directly in the master group, put them in a real group */
 	/* This will kind of mess up if you hit the item limit, but this function isn't too critical */
@@ -646,17 +646,25 @@
 			aim_ssi_addbuddy(sess, conn, cur->name, "orphans", NULL, NULL, NULL, 0);
 
 	/* Now DESTROY any buddies that are directly in the master group */
-	for (cur=sess->ssi.local; cur; cur=cur->next)
+	cur = sess->ssi.local;
+	while (cur) {
+		next = cur->next;
 		if ((cur->type == AIM_SSI_TYPE_BUDDY) && (cur->gid == 0x0000))
 			aim_ssi_delbuddy(sess, conn, cur->name, NULL);
+		cur = next;
+	}
 
 	/* Check if there are empty groups */
-	for (cur=sess->ssi.local; cur; cur=cur->next)
+	cur = sess->ssi.local;
+	while (cur) {
+		next = cur->next;
 		if (cur->type == AIM_SSI_TYPE_GROUP) {
 			aim_tlv_t *tlv = aim_gettlv(cur->data, 0x00c8, 1);
 			if (!cur->data || !tlv || !tlv->length)
 				aim_ssi_itemlist_del(&sess->ssi.local, cur);
 		}
+		cur = next;
+	}
 
 	/* Check if the master group is empty */
 	if ((cur = aim_ssi_itemlist_find(sess->ssi.local, 0x0000, 0x0000)) && (!cur->data))
--- a/src/protocols/toc/toc.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/toc/toc.c	Sat Jan 18 01:58:00 2003 +0000
@@ -1379,24 +1379,28 @@
 	return g_list_append(NULL, GAIM_AWAY_CUSTOM);
 }
 
-static void toc_do_action(struct gaim_connection *gc, char *act)
-{
-	if (!strcmp(act, "Set User Info")) {
-		show_set_info(gc);
-	} else if (!strcmp(act, "Set Dir Info")) {
-		show_set_dir(gc);
-	} else if (!strcmp(act, "Change Password")) {
-		show_change_passwd(gc);
-	}
-}
-
-static GList *toc_actions()
+static GList *toc_actions(struct gaim_connection *gc)
 {
 	GList *m = NULL;
+	struct proto_actions_menu *pam;
 
-	m = g_list_append(m, "Set User Info");
-	m = g_list_append(m, "Set Dir Info");
-	m = g_list_append(m, "Change Password");
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set User Info");
+	pam->callback = show_set_info;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Set Dir Info");
+	pam->callback = show_set_dir;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
+
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Change Password");
+	pam->callback = show_change_passwd;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -1410,7 +1414,6 @@
 	ret->list_icon = toc_list_icon;
 	ret->away_states = toc_away_states;
 	ret->actions = toc_actions;
-	ret->do_action = toc_do_action;
 	ret->buddy_menu = toc_buddy_menu;
 	ret->login = toc_login;
 	ret->close = toc_close;
--- a/src/protocols/yahoo/yahoo.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/protocols/yahoo/yahoo.c	Sat Jan 18 01:58:00 2003 +0000
@@ -1129,17 +1129,20 @@
 	g_snprintf(gc->displayname, sizeof(gc->displayname), "%s", entry);
 }
 
-static void yahoo_do_action(struct gaim_connection *gc, char *act)
+static void yahoo_show_act_id(struct gaim_connection *gc)
 {
-	if (!strcmp(act, "Activate ID")) {
-		do_prompt_dialog("Activate which ID:", gc->displayname, gc, yahoo_act_id, NULL);
-	}
+	do_prompt_dialog("Activate which ID:", gc->displayname, gc, yahoo_act_id, NULL);
 }
 
-static GList *yahoo_actions() {
+static GList *yahoo_actions(struct gaim_connection *gc) {
 	GList *m = NULL;
+	struct proto_actions_menu *pam;
 
-	m = g_list_append(m, "Activate ID");
+	pam = g_new0(struct proto_actions_menu, 1);
+	pam->label = _("Activate ID");
+	pam->callback = yahoo_show_act_id;
+	pam->gc = gc;
+	m = g_list_append(m, pam);
 
 	return m;
 }
@@ -1347,7 +1350,6 @@
 	ret->buddy_menu = yahoo_buddy_menu;
 	ret->list_icon = yahoo_list_icon;
 	ret->actions = yahoo_actions;
-	ret->do_action = yahoo_do_action;
 	ret->send_im = yahoo_send_im;
 	ret->away_states = yahoo_away_states;
 	ret->set_away = yahoo_set_away;
--- a/src/prpl.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/prpl.c	Sat Jan 18 01:58:00 2003 +0000
@@ -315,10 +315,10 @@
 	gtk_widget_show_all(window);
 }
 
-static void proto_act(GtkObject *obj, struct gaim_connection *gc)
+static void proto_act(GtkObject *obj, struct proto_actions_menu *pam)
 {
-	char *act = gtk_object_get_user_data(obj);
-	gc->prpl->do_action(gc, act);
+	if (pam->callback && pam->gc)
+		pam->callback(pam->gc);
 }
 
 void do_proto_menu()
@@ -327,6 +327,7 @@
 	GtkWidget *submenu;
 	GList *l;
 	GSList *c = connections;
+	struct proto_actions_menu *pam;
 	struct gaim_connection *gc = NULL;
 	int count = 0;
 	char buf[256];
@@ -336,20 +337,24 @@
 
 	l = gtk_container_children(GTK_CONTAINER(protomenu));
 	while (l) {
-		gtk_container_remove(GTK_CONTAINER(protomenu), GTK_WIDGET(l->data));
+		menuitem = l->data;
+		pam = gtk_object_get_data(GTK_OBJECT(menuitem), "user_data");
+		if (pam)
+			g_free(pam);
+		gtk_container_remove(GTK_CONTAINER(protomenu), GTK_WIDGET(menuitem));
 		l = l->next;
 	}
 
 	while (c) {
 		gc = c->data;
-		if (gc->prpl->actions && gc->prpl->do_action)
+		if (gc->prpl->actions && gc->login_time)
 			count++;
 		c = g_slist_next(c);
 	}
 	c = connections;
 
 	if (!count) {
-		g_snprintf(buf, sizeof(buf), "No actions available");
+		g_snprintf(buf, sizeof(buf), _("No actions available"));
 		menuitem = gtk_menu_item_new_with_label(buf);
 		gtk_menu_append(GTK_MENU(protomenu), menuitem);
 		gtk_widget_show(menuitem);
@@ -357,39 +362,35 @@
 	}
 
 	if (count == 1) {
-		GList *tmp, *act;
+		GList *act;
 		while (c) {
 			gc = c->data;
-			if (gc->prpl->actions && gc->prpl->do_action)
+			if (gc->prpl->actions && gc->login_time)
 				break;
 			c = g_slist_next(c);
 		}
 
-		tmp = act = gc->prpl->actions();
+		act = gc->prpl->actions(gc);
 
 		while (act) {
-			if (act->data == NULL) {
+			if (act->data) {
+				struct proto_actions_menu *pam = act->data;
+				menuitem = gtk_menu_item_new_with_label(pam->label);
+				gtk_menu_append(GTK_MENU(protomenu), menuitem);
+				g_signal_connect(GTK_OBJECT(menuitem), "activate",
+							G_CALLBACK(proto_act), pam);
+				gtk_object_set_data(GTK_OBJECT(menuitem), "user_data", pam);
+				gtk_widget_show(menuitem);
+			} else {
 				gaim_separator(protomenu);
-				act = g_list_next(act);
-				continue;
 			}
-
-			menuitem = gtk_menu_item_new_with_label(act->data);
-			gtk_object_set_user_data(GTK_OBJECT(menuitem), act->data);
-			gtk_menu_append(GTK_MENU(protomenu), menuitem);
-			g_signal_connect(GTK_OBJECT(menuitem), "activate",
-					   G_CALLBACK(proto_act), gc);
-			gtk_widget_show(menuitem);
-
 			act = g_list_next(act);
 		}
-
-		g_list_free(tmp);
 	} else {
 		while (c) {
-			GList *tmp, *act;
+			GList *act;
 			gc = c->data;
-			if (!gc->prpl->actions || !gc->prpl->do_action) {
+			if (!gc->prpl->actions || !gc->login_time) {
 				c = g_slist_next(c);
 				continue;
 			}
@@ -403,26 +404,22 @@
 			gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu);
 			gtk_widget_show(submenu);
 
-			tmp = act = gc->prpl->actions();
+			act = gc->prpl->actions(gc);
 
 			while (act) {
-				if (act->data == NULL) {
+				if (act->data) {
+					struct proto_actions_menu *pam = act->data;
+					menuitem = gtk_menu_item_new_with_label(pam->label);
+					gtk_menu_append(GTK_MENU(submenu), menuitem);
+					g_signal_connect(GTK_OBJECT(menuitem), "activate",
+								G_CALLBACK(proto_act), pam);
+					gtk_object_set_data(GTK_OBJECT(menuitem), "user_data", pam);
+					gtk_widget_show(menuitem);
+				} else {
 					gaim_separator(submenu);
-					act = g_list_next(act);
-					continue;
 				}
-
-				menuitem = gtk_menu_item_new_with_label(act->data);
-				gtk_object_set_user_data(GTK_OBJECT(menuitem), act->data);
-				gtk_menu_append(GTK_MENU(submenu), menuitem);
-				g_signal_connect(GTK_OBJECT(menuitem), "activate",
-						   G_CALLBACK(proto_act), gc);
-				gtk_widget_show(menuitem);
-
 				act = g_list_next(act);
 			}
-
-			g_list_free(tmp);
 			c = g_slist_next(c);
 		}
 	}
@@ -664,9 +661,9 @@
 		   msg ? msg : "",
 		   find_buddy(gc, ga->who) ? "" : _("\n\nDo you wish to add him or her to your buddy list?"));
 	if (find_buddy(gc, ga->who))
-		do_error_dialog(buf, _("Gaim - Information"), GAIM_INFO);
+		do_error_dialog(_("Gaim - Information"), buf, GAIM_INFO);
 	else
-		do_ask_dialog(buf, _("Gaim - Confirm"), ga, _("Add"), do_add, _("Cancel"), dont_add, NULL, FALSE);
+		do_ask_dialog(_("Gaim - Confirm"), buf, ga, _("Add"), do_add, _("Cancel"), dont_add, NULL, FALSE);
 }
 
 static GtkWidget *regdlg = NULL;
--- a/src/prpl.h	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/prpl.h	Sat Jan 18 01:58:00 2003 +0000
@@ -99,8 +99,7 @@
 	/* returns the XPM associated with the given user class */
 	char **(* list_icon)(int);
 	GList *(* away_states)(struct gaim_connection *gc);
-	GList *(* actions)();
-	void   (* do_action)(struct gaim_connection *, char *);
+	GList *(* actions)(struct gaim_connection *gc);
 	/* user_opts is a GList* of g_malloc'd struct proto_user_opts */
 	GList *user_opts;
 	GList *(* buddy_menu)(struct gaim_connection *, char *);
--- a/src/server.c	Sat Jan 18 01:09:59 2003 +0000
+++ b/src/server.c	Sat Jan 18 01:58:00 2003 +0000
@@ -139,8 +139,6 @@
 	gc->idle_timer = g_timeout_add(20000, check_idle, gc);
 	serv_touch_idle(gc);
 
-	time(&gc->login_time);
-
 	if (gc->prpl->options & OPT_PROTO_CORRECT_TIME)
 		serv_add_buddy(gc, gc->username);