Index: irc.h
===================================================================
--- irc.h	(revision bce78c8e6b9363175943a1b10df76fdbd87ba0c8)
+++ irc.h	(revision e54112f152c375df81a21181f755ced5f57165bc)
@@ -153,4 +153,17 @@
 };
 
+typedef enum
+{
+	IRC_CHANNEL_USER_OP = 1,
+	IRC_CHANNEL_USER_HALFOP = 2,
+	IRC_CHANNEL_USER_VOICE = 4,
+} irc_channel_user_flags_t;
+
+typedef struct irc_channel_user
+{
+	irc_user_t *iu;
+	int flags;
+} irc_channel_user_t;
+
 extern const struct bee_ui_funcs irc_ui_funcs;
 
@@ -181,5 +194,5 @@
 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu );
 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu );
-gboolean irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
+irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu );
 int irc_channel_set_topic( irc_channel_t *ic, const char *topic, const irc_user_t *who );
 gboolean irc_channel_name_ok( const char *name );
Index: irc_channel.c
===================================================================
--- irc_channel.c	(revision bce78c8e6b9363175943a1b10df76fdbd87ba0c8)
+++ irc_channel.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
@@ -26,4 +26,5 @@
 #include "bitlbee.h"
 
+static gint irc_channel_user_cmp( gconstpointer a_, gconstpointer b_ );
 static const struct irc_channel_funcs control_channel_funcs;
 
@@ -71,5 +72,9 @@
 	
 	irc->channels = g_slist_remove( irc->channels, ic );
-	g_slist_free( ic->users );
+	while( ic->users )
+	{
+		g_free( ic->users->data );
+		ic->users = g_slist_remove( ic->users, ic->users->data );
+	}
 	
 	g_free( ic->name );
@@ -82,8 +87,13 @@
 int irc_channel_add_user( irc_channel_t *ic, irc_user_t *iu )
 {
+	irc_channel_user_t *icu;
+	
 	if( irc_channel_has_user( ic, iu ) )
 		return 0;
 	
-	ic->users = g_slist_insert_sorted( ic->users, iu, irc_user_cmp );
+	icu = g_new0( irc_channel_user_t, 1 );
+	icu->iu = iu;
+	
+	ic->users = g_slist_insert_sorted( ic->users, icu, irc_channel_user_cmp );
 	
 	if( iu == ic->irc->user || ic->flags & IRC_CHANNEL_JOINED )
@@ -98,8 +108,11 @@
 int irc_channel_del_user( irc_channel_t *ic, irc_user_t *iu )
 {
-	if( !irc_channel_has_user( ic, iu ) )
+	irc_channel_user_t *icu;
+	
+	if( !( icu = irc_channel_has_user( ic, iu ) ) )
 		return 0;
 	
-	ic->users = g_slist_remove( ic->users, iu );
+	ic->users = g_slist_remove( ic->users, icu );
+	g_free( icu );
 	
 	if( ic->flags & IRC_CHANNEL_JOINED )
@@ -112,8 +125,17 @@
 }
 
-/* Currently a fairly stupid one-liner but I fear it's going to get worse. :-) */
-gboolean irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu )
-{
-	return g_slist_find( ic->users, iu ) != NULL;
+irc_channel_user_t *irc_channel_has_user( irc_channel_t *ic, irc_user_t *iu )
+{
+	GSList *l;
+	
+	for( l = ic->users; l; l = l->next )
+	{
+		irc_channel_user_t *icu = l->data;
+		
+		if( icu->iu == iu )
+			return icu;
+	}
+	
+	return NULL;
 }
 
@@ -140,4 +162,11 @@
 {
 	return strchr( CTYPES, name[0] ) != NULL && nick_ok( name + 1 );
+}
+
+static gint irc_channel_user_cmp( gconstpointer a_, gconstpointer b_ )
+{
+	const irc_channel_user_t *a = a_, *b = b_;
+	
+	return irc_user_cmp( a->iu, b->iu );
 }
 
Index: irc_send.c
===================================================================
--- irc_send.c	(revision bce78c8e6b9363175943a1b10df76fdbd87ba0c8)
+++ irc_send.c	(revision e54112f152c375df81a21181f755ced5f57165bc)
@@ -163,5 +163,6 @@
 	for( l = ic->users; l; l = l->next )
 	{
-		irc_user_t *iu = l->data;
+		irc_channel_user_t *icu = l->data;
+		irc_user_t *iu = icu->iu;
 		
 		if( strlen( namelist ) + strlen( iu->nick ) > sizeof( namelist ) - 4 )
@@ -243,7 +244,11 @@
 void irc_send_who( irc_t *irc, GSList *l, const char *channel )
 {
+	gboolean is_channel = strcmp( channel, "**" ) != 0;
+	
 	while( l )
 	{
 		irc_user_t *iu = l->data;
+		if( is_channel )
+			iu = ((irc_channel_user_t*)iu)->iu;
 		/* TODO(wilmer): Restore away/channel information here */
 		irc_send_num( irc, 352, "%s %s %s %s %s %c :0 %s",
