Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/jabber/jabber.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -157,9 +157,4 @@
 #define JCS_CLOSED  3	/* closed */
 
-
-static char *jabber_name()
-{
-	return "Jabber";
-}
 
 #define STATE_EVT(arg) if(gjc->on_state) { (gjc->on_state)(gjc, (arg) ); }
@@ -2413,11 +2408,11 @@
 }
 
-static struct prpl *my_protocol = NULL;
-
-void jabber_init(struct prpl *ret)
-{
+
+void jabber_init()
+{
+	struct prpl *ret = g_new0(struct prpl, 1);
+
 	/* the NULL's aren't required but they're nice to have */
-	ret->protocol = PROTO_JABBER;
-	ret->name = jabber_name;
+	ret->name = "jabber";
 	ret->away_states = jabber_away_states;
 	ret->actions = jabber_actions;
@@ -2442,4 +2437,4 @@
 	ret->group_buddy = jabber_group_change;
 
-	my_protocol = ret;
-}
+	register_protocol (ret);
+}
Index: protocols/msn/msn.c
===================================================================
--- protocols/msn/msn.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/msn/msn.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -26,6 +26,4 @@
 #include "nogaim.h"
 #include "msn.h"
-
-static struct prpl *my_protocol = NULL;
 
 static void msn_login( struct aim_user *acct )
@@ -375,7 +373,8 @@
 }
 
-void msn_init(struct prpl *ret)
-{
-	ret->protocol = PROTO_MSN;
+void msn_init()
+{
+	struct prpl *ret = g_new0(struct prpl, 1);
+	ret->name = "msn";
 	ret->login = msn_login;
 	ret->close = msn_close;
@@ -399,4 +398,4 @@
 	ret->send_typing = msn_send_typing;
 
-	my_protocol = ret;
-}
+	register_protocol(ret);
+}
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/nogaim.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -39,7 +39,4 @@
 #include <iconv.h>
 
-struct prpl *proto_prpl[PROTO_MAX];
-char proto_name[PROTO_MAX][8] = { "TOC", "OSCAR", "YAHOO", "ICQ", "MSN", "", "", "", "JABBER", "", "", "", "", "", "", "" };
-
 static char *proto_away_alias[7][5] =
 {
@@ -58,28 +55,93 @@
 GSList *connections;
 
+gboolean load_plugin(char *path)
+{
+	void (*init_function) (void);
+	
+	GModule *mod = g_module_open(path, G_MODULE_BIND_LAZY);
+
+	if(!mod) {
+		log_message(LOGLVL_ERROR, "Can't find `%s', not loading", path);
+		return FALSE;
+	}
+
+	if(!g_module_symbol(mod,"init_plugin",(gpointer *) &init_function)) {
+		log_message(LOGLVL_WARNING, "Can't find function `init_plugin' in `%s'\n", path);
+		return FALSE;
+	}
+
+	init_function();
+
+	return TRUE;
+}
 
 /* nogaim.c */
 
+GList *protocols = NULL;
+  
+void register_protocol (struct prpl *p)
+{
+	protocols = g_list_append(protocols, p);
+}
+
+ 
+struct prpl *find_protocol(const char *name)
+{
+	GList *gl;
+	for (gl = protocols; gl; gl = gl->next) 
+ 	{
+ 		struct prpl *proto = gl->data;
+ 		if(!g_strcasecmp(proto->name, name)) 
+			return proto;
+ 	}
+ 	return NULL;
+}
+
+/* nogaim.c */
 void nogaim_init()
 {
-	proto_prpl[PROTO_MSN] = g_new0 ( struct prpl, 1 );
+	GDir *dir;
+	GError *error = NULL;
+
 #ifdef WITH_MSN
-	msn_init( proto_prpl[PROTO_MSN] );
+	extern void msn_init();
+	msn_init();
 #endif
 
-	proto_prpl[PROTO_OSCAR] = g_new0( struct prpl, 1 );
 #ifdef WITH_OSCAR
-	oscar_init( proto_prpl[PROTO_OSCAR] );
+	extern void oscar_init();
+	oscar_init();
 #endif
 	
-	proto_prpl[PROTO_YAHOO] = g_new0( struct prpl, 1 );
 #ifdef WITH_YAHOO
-	byahoo_init( proto_prpl[PROTO_YAHOO] );
+	extern void byahoo_init();
+	byahoo_init();
 #endif
 	
-	proto_prpl[PROTO_JABBER] = g_new0( struct prpl, 1 );
 #ifdef WITH_JABBER
-	jabber_init( proto_prpl[PROTO_JABBER] );
+	extern void jabber_init();
+	jabber_init();
 #endif
+
+	dir = g_dir_open(PLUGINDIR, 0, &error);
+
+	if (dir) {
+		const gchar *entry;
+		char *path;
+
+		while ((entry = g_dir_read_name(dir))) {
+			path = g_build_filename(PLUGINDIR, entry, NULL);
+			if(!path) {
+				log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry);
+				continue;
+			}
+
+			load_plugin(path);
+
+			g_free(path);
+		}
+
+		g_dir_close(dir);
+	}
 }
 
@@ -122,5 +184,5 @@
 			gc->prpl->set_away( gc, s, away );
 			if( set_getint( gc->irc, "debug" ) )
-				irc_usermsg( gc->irc, "Setting away state for %s to %s", proto_name[gc->protocol], s );
+				irc_usermsg( gc->irc, "Setting away state for %s to %s", gc->prpl->name, s );
 		}
 		else
@@ -168,7 +230,7 @@
    way for now because I don't want to touch the Gaim code too much since
    it's not going to be here for too long anymore. */
-int handle_cmp( char *a, char *b, int protocol )
-{
-	if( protocol == PROTO_TOC || protocol == PROTO_ICQ )
+int handle_cmp( char *a, char *b, struct prpl *protocol )
+{
+	if( !strcmp(protocol->name, "oscar") )
 	{
 		/* AIM, being teh evil, thinks it's cool that users can put
@@ -210,6 +272,5 @@
 	gc = g_new0( struct gaim_connection, 1 );
 	
-	gc->protocol = user->protocol;
-	gc->prpl = proto_prpl[gc->protocol];
+	gc->prpl = user->prpl;
 	g_snprintf( gc->username, sizeof( gc->username ), "%s", user->username );
 	g_snprintf( gc->password, sizeof( gc->password ), "%s", user->password );
@@ -254,5 +315,5 @@
 void set_login_progress( struct gaim_connection *gc, int step, char *msg )
 {
-	irc_usermsg( gc->irc, "%s(%s) - Logging in: %s", proto_name[gc->protocol], gc->username, msg );
+	irc_usermsg( gc->irc, "%s(%s) - Logging in: %s", gc->prpl->name, gc->username, msg );
 }
 
@@ -260,5 +321,5 @@
 void hide_login_progress( struct gaim_connection *gc, char *msg )
 {
-	irc_usermsg( gc->irc, "%s(%s) - Login error: %s", proto_name[gc->protocol], gc->username, msg );
+	irc_usermsg( gc->irc, "%s(%s) - Login error: %s", gc->prpl->name, gc->username, msg );
 }
 
@@ -266,5 +327,5 @@
 void hide_login_progress_error( struct gaim_connection *gc, char *msg )
 {
-	irc_usermsg( gc->irc, "%s(%s) - Logged out: %s", proto_name[gc->protocol], gc->username, msg );
+	irc_usermsg( gc->irc, "%s(%s) - Logged out: %s", gc->prpl->name, gc->username, msg );
 }
 
@@ -289,5 +350,5 @@
 		strip_html( msg );
 	
-	irc_usermsg( gc->irc, "%s(%s) - %s", proto_name[gc->protocol], gc->username, msg );
+	irc_usermsg( gc->irc, "%s(%s) - %s", gc->prpl->name, gc->username, msg );
 }
 
@@ -314,5 +375,5 @@
 	u = user_find( gc->irc, gc->irc->nick );
 	
-	irc_usermsg( gc->irc, "%s(%s) - Logged in", proto_name[gc->protocol], gc->username );
+	irc_usermsg( gc->irc, "%s(%s) - Logged in", gc->prpl->name, gc->username );
 	
 	gc->keepalive = g_timeout_add( 60000, send_keepalive, gc );
@@ -321,5 +382,5 @@
 	if( u && u->away ) proto_away( gc, u->away );
 	
-	if( gc->protocol == PROTO_ICQ )
+ 	if( !strcmp(gc->prpl->name, "icq") )
 	{
 		for( u = gc->irc->users; u; u = u->next )
@@ -361,5 +422,5 @@
 	account_t *a;
 	
-	irc_usermsg( gc->irc, "%s(%s) - Signing off..", proto_name[gc->protocol], gc->username );
+	irc_usermsg( gc->irc, "%s(%s) - Signing off..", gc->prpl->name, gc->username );
 
 	gaim_input_remove( gc->keepalive );
@@ -393,5 +454,5 @@
 	{
 		int delay = set_getint( irc, "auto_reconnect_delay" );
-		irc_usermsg( gc->irc, "%s(%s) - Reconnecting in %d seconds..", proto_name[gc->protocol], gc->username, delay);
+		irc_usermsg( gc->irc, "%s(%s) - Reconnecting in %d seconds..", gc->prpl->name, gc->username, delay);
 		
 		a->reconnect = 1;
@@ -449,5 +510,5 @@
 	
 	memset( nick, 0, MAX_NICK_LENGTH + 1 );
-	strcpy( nick, nick_get( gc->irc, handle, gc->protocol, realname ) );
+	strcpy( nick, nick_get( gc->irc, handle, gc->prpl, realname ) );
 	
 	u = user_add( gc->irc, nick );
@@ -473,5 +534,5 @@
 	else
 	{
-		u->host = g_strdup( proto_name[gc->user->protocol] );
+		u->host = g_strdup( gc->user->prpl->name );
 		u->user = g_strdup( handle );
 	}
@@ -567,5 +628,5 @@
 			if( set_getint( gc->irc, "debug" ) || g_strcasecmp( set_getstr( gc->irc, "handle_unknown" ), "ignore" ) != 0 )
 			{
-				irc_usermsg( gc->irc, "serv_got_update() for handle %s on connection %s(%s):", handle, proto_name[gc->protocol], gc->username );
+				irc_usermsg( gc->irc, "serv_got_update() for handle %s on connection %s(%s):", handle, gc->prpl->name, gc->username );
 				irc_usermsg( gc->irc, "loggedin = %d, type = %d", loggedin, type );
 			}
@@ -602,9 +663,9 @@
 	}
 	
-	if( ( type & UC_UNAVAILABLE ) && ( gc->protocol == PROTO_OSCAR || gc->protocol == PROTO_TOC ) )
+	if( ( type & UC_UNAVAILABLE ) && ( !strcmp(gc->prpl->name, "oscar") || !strcmp(gc->prpl->name, "icq")) )
 	{
 		u->away = g_strdup( "Away" );
 	}
-	else if( ( type & UC_UNAVAILABLE ) && ( gc->protocol == PROTO_JABBER ) )
+	else if( ( type & UC_UNAVAILABLE ) && ( !strcmp(gc->prpl->name, "jabber") ) )
 	{
 		if( type & UC_DND )
@@ -648,5 +709,5 @@
 		{
 			if( set_getint( irc, "debug" ) )
-				irc_usermsg( irc, "Ignoring message from unknown handle %s on connection %s(%s)", handle, proto_name[gc->protocol], gc->username );
+				irc_usermsg( irc, "Ignoring message from unknown handle %s on connection %s(%s)", handle, gc->prpl->name, gc->username );
 			
 			return;
@@ -670,5 +731,5 @@
 		else
 		{
-			irc_usermsg( irc, "Message from unknown handle %s on connection %s(%s):", handle, proto_name[gc->protocol], gc->username );
+			irc_usermsg( irc, "Message from unknown handle %s on connection %s(%s):", handle, gc->prpl->name, gc->username );
 			u = user_find( irc, irc->mynick );
 		}
@@ -836,5 +897,5 @@
 	
 	/* It might be yourself! */
-	if( handle_cmp ( handle, b->gc->user->username, b->gc->protocol ) == 0 )
+	if( handle_cmp ( handle, b->gc->user->username, b->gc->prpl ) == 0 )
 	{
 		u = user_find( b->gc->irc, b->gc->irc->nick );
Index: protocols/nogaim.h
===================================================================
--- protocols/nogaim.h	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/nogaim.h	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -72,5 +72,4 @@
 	/* we need to do either oscar or TOC */
 	/* we make this as an int in case if we want to add more protocols later */
-	int protocol;
 	struct prpl *prpl;
 	guint32 flags;
@@ -152,5 +151,5 @@
 	char user_info[2048];
 	int options;
-	int protocol;
+	struct prpl *prpl;
 	/* prpls can use this to save information about the user,
 	 * like which server to connect to, etc */
@@ -161,8 +160,26 @@
 };
 
+struct ft 
+{
+	const char *filename;
+	
+	/* Total number of bytes in file */
+	size_t total_bytes;
+	
+	/* Current number of bytes received */
+	size_t cur_bytes;
+};
+
+struct ft_request 
+{
+	const char *filename;
+	struct gaim_connection *gc;
+};
+
+typedef void (*ft_recv_handler) (struct ft *, void *data, size_t len);
+
 struct prpl {
-	int protocol;
 	int options;
-	char *(* name)();
+	const char *name;
 
 	/* for ICQ and Yahoo, who have off/on per-conversation options */
@@ -217,24 +234,13 @@
 	void (* group_buddy)	(struct gaim_connection *, char *who, char *old_group, char *new_group);
 
+	/* file transfers */
+	struct ft_send_req *(* req_send_file) (struct gaim_connection *, const char *file);
+	void (* send_file_part) (struct gaim_connection *, struct ft*, void *data, size_t length);
+	void (* accept_recv_file) (struct gaim_connection *, struct ft*, ft_recv_handler);
+
 	void (* buddy_free)	(struct buddy *);
 
 	char *(* get_status_string) (struct gaim_connection *gc, int stat);
 };
-
-#define PROTO_TOC	0
-#define PROTO_OSCAR	1
-#define PROTO_YAHOO	2
-#define PROTO_ICQ	3
-#define PROTO_MSN	4
-#define PROTO_IRC	5
-#define PROTO_FTP	6
-#define PROTO_VGATE	7
-#define PROTO_JABBER	8
-#define PROTO_NAPSTER	9
-#define PROTO_ZEPHYR	10
-#define PROTO_GADUGADU	11
-#define PROTO_MAX	16
-
-extern char proto_name[PROTO_MAX][8];
 
 #define UC_UNAVAILABLE  1
@@ -247,5 +253,6 @@
 
 G_MODULE_EXPORT GSList *get_connections();
-extern struct prpl *proto_prpl[16];
+G_MODULE_EXPORT struct prpl *find_protocol(const char *name);
+G_MODULE_EXPORT void register_protocol(struct prpl *);
 
 /* nogaim.c */
@@ -259,5 +266,5 @@
 int proto_away( struct gaim_connection *gc, char *away );
 char *set_eval_away_devoice( irc_t *irc, set_t *set, char *value );
-int handle_cmp( char *a, char *b, int protocol );
+int handle_cmp( char *a, char *b, struct prpl *protocol );
 
 gboolean auto_reconnect( gpointer data );
@@ -318,23 +325,9 @@
 G_MODULE_EXPORT void info_string_append(GString *str, char *newline, char *name, char *value);
 
-#ifdef WITH_MSN
-/* msn.c */
-G_MODULE_EXPORT void msn_init( struct prpl *ret );
-#endif
-
-#ifdef WITH_OSCAR
-/* oscar.c */
-G_MODULE_EXPORT void oscar_init( struct prpl *ret );
-#endif
-
-#ifdef WITH_JABBER
-/* jabber.c */
-G_MODULE_EXPORT void jabber_init( struct prpl *ret );
-#endif
-
-#ifdef WITH_YAHOO
-/* yahoo.c */
-G_MODULE_EXPORT void byahoo_init( struct prpl *ret );
-#endif
+/* file transfers */
+G_MODULE_EXPORT void ft_progress( struct ft *, int);
+G_MODULE_EXPORT void ft_incoming( struct ft_request * );
+G_MODULE_EXPORT void ft_accepted( struct ft_request *, struct ft *);
+G_MODULE_EXPORT void ft_denied( struct ft_request *, const char *reason);
 
 /* prefs.c */
Index: protocols/oscar/oscar.c
===================================================================
--- protocols/oscar/oscar.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/oscar/oscar.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -364,8 +364,6 @@
 		odata->icq = TRUE;
 		/* this is odd but it's necessary for a proper do_import and do_export */
-		gc->protocol = PROTO_ICQ;
 		gc->password[8] = 0;
 	} else {
-		gc->protocol = PROTO_TOC;
 		gc->flags |= OPT_CONN_HTML;
 	}
@@ -2467,8 +2465,8 @@
 }
 
-static struct prpl *my_protocol = NULL;
-
-void oscar_init(struct prpl *ret) {
-	ret->protocol = PROTO_OSCAR;
+void oscar_init() 
+{
+	struct prpl *ret = g_new0(struct prpl, 1);
+	ret->name = "oscar";
 	ret->away_states = oscar_away_states;
 	ret->login = oscar_login;
@@ -2488,4 +2486,4 @@
 	ret->get_status_string = oscar_get_status_string;
 
-	my_protocol = ret;
-}
+	register_protocol(ret);
+}
Index: protocols/proxy.c
===================================================================
--- protocols/proxy.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/proxy.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -50,14 +50,4 @@
 #define GAIM_ERR_COND   (G_IO_HUP | G_IO_ERR | G_IO_NVAL)
 
-/*FIXME*		
-	#ifndef _WIN32
-		if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
-			closesocket(fd);
-			g_free(phb);
-			return -1;
-		}
-		fcntl(fd, F_SETFL, 0);
-#endif*/
-
 char proxyhost[128] = "";
 int proxyport = 0;
Index: protocols/yahoo/yahoo.c
===================================================================
--- protocols/yahoo/yahoo.c	(revision b7d3cc34f68dab7b8f7d0777711317b334fc2219)
+++ protocols/yahoo/yahoo.c	(revision d1d677615e12d759b6cdf7ce23a493bc055ef37f)
@@ -64,10 +64,4 @@
 };
 
-static char *yahoo_name()
-{
-	return "Yahoo";
-}
-
-static struct prpl *my_protocol = NULL;
 static GSList *byahoo_inputs = NULL;
 static int byahoo_chat_id = 0;
@@ -396,13 +390,12 @@
 }
 
-void byahoo_init( struct prpl *ret )
-{
-	ret->protocol = PROTO_YAHOO;
-	ret->name = yahoo_name;
+void byahoo_init( )
+{
+	struct prpl *ret = g_new0(struct prpl, 1);
+	ret->name = "yahoo";
 	
 	ret->login = byahoo_login;
 	ret->close = byahoo_close;
 	ret->send_im = byahoo_send_im;
-	ret->send_typing = byahoo_send_typing;
 	ret->get_info = byahoo_get_info;
 	ret->away_states = byahoo_away_states;
@@ -412,4 +405,5 @@
 	ret->remove_buddy = byahoo_remove_buddy;
 	ret->get_status_string = byahoo_get_status_string;
+	ret->send_typing = byahoo_send_typing;
 	
 	ret->chat_send = byahoo_chat_send;
@@ -418,5 +412,5 @@
 	ret->chat_open = byahoo_chat_open;
 	
-	my_protocol = ret;
+	register_protocol(ret);
 }
 
@@ -432,5 +426,5 @@
 		yd = gc->proto_data;
 		
-		if( gc->protocol == PROTO_YAHOO && yd->y2_id == id )
+		if( !strcmp(gc->prpl->name, "yahoo") && yd->y2_id == id )
 			return( gc );
 	}
