changeset 1086:ce201056e7a6

[gaim-migrate @ 1096] adam is obviously very bored; he hacked gaim. other good prpl-related stuff. committer: Tailor Script <tailor@pidgin.im>
author Eric Warmenhoven <eric@warmenhoven.org>
date Sun, 12 Nov 2000 14:14:12 +0000
parents 8da0bf36fb99
children 56c7ceb986a8
files PRPL doc/CREDITS src/multi.c src/oscar.c
diffstat 4 files changed, 172 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/PRPL	Sun Nov 12 13:24:09 2000 +0000
+++ b/PRPL	Sun Nov 12 14:14:12 2000 +0000
@@ -1,45 +1,5 @@
 Protocol Plugins. What EveryBuddy should have been.
 
-Protocol Plugins are easier than GUI plugins. This is because there is necessarily a limited set
-of server functions; protocols are limited. What a programmer can do with a UI is limitless.
-
-In order to design a framework for which Protocol Plugins can work, we must first think about
-which protocols can be pluginized. (Henceforth PRPL will stand for both the Protocol Plugin
-system and an individual Protocol Plugin.)
-
-Oscar. TOC. Yahoo. MSN. ICQ. FTP. IRC.
-
-There is a longer list. Note that FTP is in the list presented. FTP has basic functions similar
-to those of the others. The basic functions that must be performed are:
-
-Sign on. (log in)
-Sign off.
-Send and receive messages.
-
-There really isn't much more to it than that. There are, then, additional functions that some
-protocols implement:
-
-Chat.
-File Transfer.
-Away/Idle. (states)
-Directory Info.
-
-Before PRPL there was a slight abstraction in the code. The UI simply needed to call serv_login,
-and that function would decide between the protocols, which function to call. It did that with
-an if-elseif-else series.
-
-With PRPL, each PRPL is stored in a struct. The structs are then kept in a GSList. The serv_
-functions then simply need to search the GSList for the correct protocol, and call the desired
-function. The struct holds void * references to the desired functions. serv_* simply needs to
-call that function. (Even better, each connection has a reference to the PRPL struct it uses;
-this will reduce search time.)
-
-A new PRPL can be loaded at any time. They can be either static or dynamic code. When a new
-protocol is loaded, gaim will call its protocol_init function, which is expected to return a
-pointer to the aforementioned struct. If it returns NULL, the PRPL will not be loaded. (This is
-not entirely true and needs to be modified in the code to work similarly to how it's decscribed
-here.)
-
 Each PRPL needs to have a unique identifier. In the pre-PRPL system TOC was 0 and Oscar was 1.
 This identifier can be found in prpl.h. They are pre-assigned. PROTO_TOC is still 0, PROTO_OSCAR
 is still 1. The protocol_init function is expected to set the struct's protocol member to the
@@ -52,25 +12,6 @@
 
 ======
 
-In order to test that PRPL was working with as little work as possible I made Oscar a plugin. In
-order to use Oscar as a plugin, first recompile gaim with the make variable DEBUG_CFLAGS set to
--DDYNAMIC_OSCAR, e.g.
-
-/usr/src/gaim $ make DEBUG_CFLAGS=-DDYNAMIC_OSCAR
-
-This will then remove Oscar support from the code (though it will still link with libfaim. However,
-gaim does not need to link to libfaim itself). Making the Oscar plugin is straight-forward; simply
-make oscar.so in the plugins directory, e.g.
-
-/usr/src/gaim/plugins $ make oscar.so
-
-You will then be presented with a gaim binary in src/gaim and the Oscar plugin in plugins/oscar.so.
-Simply load the oscar.so file from the normal plugin window. This will set up everything necessary.
-You may unload the plugin at any time, but the protocol will still be loaded. This may or may not
-be a problem and may or may not be fixed at a later point in time.
-
-======
-
 I guess I should document how to write a PRPL.
 
 The first thing to do is to write your init function. It should be delcared
@@ -85,7 +26,7 @@
 	load_protocol(my_proto_init);
 
 and return a non-negative int. Then compile as a plugin, load the .so file, and you're set. If you're
-going to load it dynamically, extern the my_proto_init function, and in prpl.c, call load_protocol.
+going to load it statically, extern the my_proto_init function, and in prpl.c, call load_protocol.
 
 Your PRPL needs to have a login function, which ideally should set up a gdk_input watcher. When you
 want to indicate that the account is online, simply call account_online(struct gaim_connection *).
@@ -93,8 +34,12 @@
 gaim.h for a (partial?) list).
 
 When the UI wants to send something via the server, it will call the appropriate function that you set
-in your PRPL, if it's non-NULL.
+in your PRPL, if it's non-NULL. The only function that is absolutely critical is name. Without name
+gaim will probably crash. You don't even need login, just name. (You need login to do anything useful
+though.)
 
-There's currently no way to unload a PRPL, even if compiled dynamically and the plugin is removed. If
-you do remove a dynamic PRPL and try to load a new version of it, you will still be using the old
-version. Hopefully I can figure out how to fix this. Maybe it's not that important.
+The best example to copy is probably Rob's IRC plugin, in plugins/irc.c. The most important functions
+for gaim interaction are at the bottom (irc_init, gaim_plugin_init, and gaim_plugin_remove). The
+rest of it is the protocol implementation.
+
+Sorry for the formatting. My Eterm is 105 characters wide.
--- a/doc/CREDITS	Sun Nov 12 13:24:09 2000 +0000
+++ b/doc/CREDITS	Sun Nov 12 14:14:12 2000 +0000
@@ -12,6 +12,10 @@
 
 Other Contributors:
 
+Adam Fritzler (mid)
+	Wrote libfaim, and added stuff to oscar.c to let people use
+	a proxy with libfaim.
+
 Thanks to Torrey Searle for the spell checking code that
 accompanies the gtk_text box :)
 
--- a/src/multi.c	Sun Nov 12 13:24:09 2000 +0000
+++ b/src/multi.c	Sun Nov 12 14:14:12 2000 +0000
@@ -264,10 +264,16 @@
 static void set_prot(GtkWidget *opt, int proto)
 {
 	struct aim_user *u = gtk_object_get_user_data(GTK_OBJECT(opt));
-	if (u) {
+	if (u && (u->tmp_protocol != proto)) {
+		int i;
+		for (i = 0; i < 6; i++)
+			u->proto_opt[i][0] = '\0';
 		u->tmp_protocol = proto;
 		generate_options(u, u->main);
-	} else {
+	} else if (tmpusr.tmp_protocol != proto) {
+		int i;
+		for (i = 0; i < 6; i++)
+			tmpusr.proto_opt[i][0] = '\0';
 		tmpusr.tmp_protocol = tmpusr.protocol = proto;
 		generate_options(NULL, newmain);
 	}
--- a/src/oscar.c	Sun Nov 12 13:24:09 2000 +0000
+++ b/src/oscar.c	Sun Nov 12 14:14:12 2000 +0000
@@ -20,8 +20,6 @@
  *
  */
 
-#ifndef DYNAMIC_OSCAR
-
 #ifdef HAVE_CONFIG_H
 #include "../config.h"
 #endif
@@ -51,6 +49,12 @@
 #include "pixmaps/dt_icon.xpm"
 #include "pixmaps/free_icon.xpm"
 
+/* constants to identify proto_opts */
+#define USEROPT_AUTH      0
+#define USEROPT_AUTHPORT  1
+#define USEROPT_SOCKSHOST 2
+#define USEROPT_SOCKSPORT 3
+
 int gaim_caps = AIM_CAPS_CHAT | AIM_CAPS_SENDFILE | AIM_CAPS_GETFILE |
 		AIM_CAPS_VOICE | AIM_CAPS_IMIMAGE | AIM_CAPS_BUDDYICON;
 
@@ -303,6 +307,7 @@
 	struct aim_session_t *sess;
 	struct aim_conn_t *conn;
 	char buf[256];
+	char *finalauth = NULL;
 	struct gaim_connection *gc = new_gaim_conn(PROTO_OSCAR, user->username, user->password);
 	struct oscar_data *odata = gc->proto_data = g_new0(struct oscar_data, 1);
 	gc->user = user;
@@ -311,18 +316,42 @@
 	debug_print(debug_buff);
 
 	sess = g_new0(struct aim_session_t, 1);
+
 	aim_session_init(sess, AIM_SESS_FLAGS_NONBLOCKCONNECT);
+
+	if (user->proto_opt[USEROPT_SOCKSHOST][0]) {
+		char *finalproxy;
+		if (user->proto_opt[USEROPT_SOCKSPORT][0])
+			finalproxy = g_strconcat(user->proto_opt[USEROPT_SOCKSHOST], ":",
+					user->proto_opt[USEROPT_SOCKSPORT], NULL);
+		else
+			finalproxy = g_strdup(user->proto_opt[USEROPT_SOCKSHOST]);
+		aim_setupproxy(sess, finalproxy, NULL, NULL);
+		g_free(finalproxy);
+	}
+
+	if (user->proto_opt[USEROPT_AUTH][0]) {
+		if (user->proto_opt[USEROPT_AUTHPORT][0])
+			finalauth = g_strconcat(user->proto_opt[USEROPT_AUTH], ":",
+					user->proto_opt[USEROPT_AUTHPORT], NULL);
+		else
+			finalauth = g_strdup(user->proto_opt[USEROPT_AUTH]);
+	}
+
 	/* we need an immediate queue because we don't use a while-loop to
 	 * see if things need to be sent. */
 	sess->tx_enqueue = &aim_tx_enqueue__immediate;
 	odata->sess = sess;
 
-	sprintf(buf, _("Looking up %s"), FAIM_LOGIN_SERVER);
+	sprintf(buf, _("Looking up %s"), finalauth ? finalauth : FAIM_LOGIN_SERVER);
 	set_login_progress(gc, 1, buf);
 	/* this creates a possible race condition, but hey, what can you do */
 	while (gtk_events_pending())
 		gtk_main_iteration();
-	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, FAIM_LOGIN_SERVER);
+	conn = aim_newconn(sess, AIM_CONN_TYPE_AUTH, finalauth ? finalauth : FAIM_LOGIN_SERVER);
+
+        if (finalauth)
+                g_free(finalauth);
 
 	if (conn == NULL) {
 		debug_print(_("internal connection error\n"));
@@ -1680,11 +1709,129 @@
 	g_free(n);
 }
 
+
+/* weeee */
+static void oscar_print_option(GtkEntry *entry, struct aim_user *user) {
+        int entrynum;
+
+        entrynum = (int) gtk_object_get_user_data(GTK_OBJECT(entry));
+ 
+	if (entrynum == USEROPT_AUTH) {
+		g_snprintf(user->proto_opt[USEROPT_AUTH],
+                           sizeof(user->proto_opt[USEROPT_AUTH]), 
+                           "%s", gtk_entry_get_text(entry));
+	} else if (entrynum == USEROPT_AUTHPORT) {
+		g_snprintf(user->proto_opt[USEROPT_AUTHPORT], 
+                           sizeof(user->proto_opt[USEROPT_AUTHPORT]), 
+                           "%s", gtk_entry_get_text(entry));
+	} else if (entrynum == USEROPT_SOCKSHOST) {
+		g_snprintf(user->proto_opt[USEROPT_SOCKSHOST], 
+                           sizeof(user->proto_opt[USEROPT_SOCKSHOST]), 
+                           "%s", gtk_entry_get_text(entry));
+	} else if (entrynum == USEROPT_SOCKSPORT) {
+		g_snprintf(user->proto_opt[USEROPT_SOCKSPORT], 
+                           sizeof(user->proto_opt[USEROPT_SOCKSPORT]), 
+                           "%s", gtk_entry_get_text(entry));
+        } 
+}
+
+static void oscar_user_opts(GtkWidget *book, struct aim_user *user) {
+	/* so here, we create the new notebook page */
+	GtkWidget *vbox;
+	GtkWidget *hbox;
+	GtkWidget *label;
+	GtkWidget *entry;
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_notebook_append_page(GTK_NOTEBOOK(book), vbox,
+			gtk_label_new("OSCAR Options"));
+	gtk_widget_show(vbox);
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	gtk_widget_show(hbox);
+
+	label = gtk_label_new("Authorizer:");
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	entry = gtk_entry_new();
+	gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+	gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_AUTH);
+	gtk_signal_connect(GTK_OBJECT(entry), "changed",
+			   GTK_SIGNAL_FUNC(oscar_print_option), user);
+	if (user->proto_opt[USEROPT_AUTH][0]) {
+		debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTH]);
+		gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTH]);
+	} else
+		gtk_entry_set_text(GTK_ENTRY(entry), "login.oscar.aol.com");
+	gtk_widget_show(entry);
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	gtk_widget_show(hbox);
+
+	label = gtk_label_new("Authorizer Port:");
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	entry = gtk_entry_new();
+	gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+	gtk_object_set_user_data(GTK_OBJECT(entry), (void *)1);
+	gtk_signal_connect(GTK_OBJECT(entry), "changed",
+			   GTK_SIGNAL_FUNC(oscar_print_option), user);
+	if (user->proto_opt[USEROPT_AUTHPORT][0]) {
+		debug_printf("setting text %s\n", user->proto_opt[USEROPT_AUTHPORT]);
+		gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_AUTHPORT]);
+	} else
+		gtk_entry_set_text(GTK_ENTRY(entry), "5190");
+	gtk_widget_show(entry);
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	gtk_widget_show(hbox);
+
+	label = gtk_label_new("SOCKS5 Host:");
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	entry = gtk_entry_new();
+	gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+	gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_SOCKSHOST);
+	gtk_signal_connect(GTK_OBJECT(entry), "changed",
+			   GTK_SIGNAL_FUNC(oscar_print_option), user);
+	if (user->proto_opt[USEROPT_SOCKSHOST][0]) {
+		debug_printf("setting text %s\n", user->proto_opt[USEROPT_SOCKSHOST]);
+		gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_SOCKSHOST]);
+	}
+	gtk_widget_show(entry);
+
+	hbox = gtk_hbox_new(FALSE, 0);
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 5);
+	gtk_widget_show(hbox);
+
+	label = gtk_label_new("SOCKS5 Port:");
+	gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+	gtk_widget_show(label);
+
+	entry = gtk_entry_new();
+	gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
+	gtk_object_set_user_data(GTK_OBJECT(entry), (void *)USEROPT_SOCKSPORT);
+	gtk_signal_connect(GTK_OBJECT(entry), "changed",
+			   GTK_SIGNAL_FUNC(oscar_print_option), user);
+	if (user->proto_opt[USEROPT_SOCKSPORT][0]) {
+		debug_printf("setting text %s\n", user->proto_opt[USEROPT_SOCKSPORT]);
+		gtk_entry_set_text(GTK_ENTRY(entry), user->proto_opt[USEROPT_SOCKSPORT]);
+	}
+	gtk_widget_show(entry);
+}
+
 void oscar_init(struct prpl *ret) {
 	ret->protocol = PROTO_OSCAR;
 	ret->name = oscar_name;
 	ret->list_icon = oscar_list_icon;
 	ret->action_menu = oscar_action_menu;
+	ret->user_opts = oscar_user_opts;
 	ret->login = oscar_login;
 	ret->close = oscar_close;
 	ret->send_im = oscar_send_im;
@@ -1714,5 +1861,3 @@
 	ret->chat_send = oscar_chat_send;
 	ret->keepalive = oscar_keepalive;
 }
-
-#endif