=== modified file 'kali/controller.py'
--- kali/controller.py	2012-01-15 17:02:41 +0000
+++ kali/controller.py	2013-05-27 15:38:24 +0000
@@ -201,7 +201,7 @@
         self.ctrl = controller
         self.store = self.ctrl.store
         self.cid = ''.join(n for n in self.ctrl.ids.next())
-        self.uid = self.ctrl.params['sid'] + self.cid 
+        self.uid = self.ctrl.params['sid'] + self.cid
         self.avatars = {}
 
     def event_connected(self, protocol):
@@ -324,6 +324,7 @@
         super(User, self).__init__(*a, **kw)
         self.registered = False
         self.channels = set()
+        self.status = {}
 
 
 class Channel(record('name'), _ModesMixin):
@@ -340,7 +341,7 @@
     @type lists: C{{mode: [values]}}
 
     @ivar users: The users currently joined to the channel.
-    @type users: C{list}
+    @type users: C{dict}
     """
     def __init__(self, *a, **kw):
         super(Channel, self).__init__(*a, **kw)
@@ -456,12 +457,15 @@
         channel.lists[mode].remove(param)
 
     def event_userStatusAdded(self, source, target, mode, param):
-        channel = self.getChannel(target)
-        channel.users[param].status.add(mode)
+        channels = self.getChannel(target).users[param].status
+        status = channels.get(target, None)
+        if not status:
+            status = channels[target] = set()
+        status.add(mode)
 
     def event_userStatusRemoved(self, source, target, mode, param):
         channel = self.getChannel(target)
-        channel.users[param].status.remove(mode)
+        channel.users[param].status[target].remove(mode)
 
     def event_joined(self, channelName, nick):
         try:
@@ -470,7 +474,7 @@
             channel = self.channels[channelName] = Channel(channelName)
 
         user = self.getUser(nick)
-        channel.users[user] = {}
+        channel.users[nick] = user
         user.channels.add(channel)
 
     def event_parted(self, channelName, nick, message):

=== modified file 'kali/protocol.py'
--- kali/protocol.py	2012-01-05 15:56:39 +0000
+++ kali/protocol.py	2013-05-27 15:38:24 +0000
@@ -47,6 +47,7 @@
 
     if ' :' in s:
         s, trailing = s.split(' :', 1)
+        trailing = ':' + trailing
 
     args = s.split()
     if trailing:
@@ -71,7 +72,7 @@
     @type params: C{list}
 
     @returns: (added, removed) modes
-    @rtype: C{([(mode, param)], [(mode, param]))}
+    @rtype: C{([(mode, param)], [(mode, param)])}
     """
     if len(modes) == 0:
         raise IRCBadModes('Empty mode string')
@@ -346,11 +347,26 @@
         else:
             self.services.event('channelFlagUnset', source, target, mode)
 
-    def irc_FJOIN(self, source, channel, timestamp, users):
+    def irc_FJOIN(self, source, channel, timestamp, modes, *args):
+        args = list(args)
+        params = []
+        if ':' in args[-1]:
+            users = args.pop().lstrip(':')
+
+        params = args
+        modes = parseModes(modes, params, (self.channelParamModes,''))
         for user in users.split():
-            prefixes, nick = user.split(',', 1)
+            try:
+                prefixes, nick = user.split(',', 1)
+            except ValueError:
+                prefixes, nick = None, user
             self.services.event('joined', channel, nick)
-            # XXX: translate the prefixes into channel mode changes
+            if prefixes:
+                for prefix in prefixes:
+                    self.addMode_channel(source, channel, prefix, nick)
+
+        for mode in modes[0]:
+            self.addMode_channel(source, channel, *mode)
 
     def irc_JOIN(self, source, channels, timestamp):
         for channel in channels.split(','):
@@ -374,9 +390,11 @@
         if len(params) == 1:
             pass
         else:
+            #XXX: modeparams aren't always present.
             paramNames = 'cid timestamp nick hostname fakehost username ip signontime modes modeparams realname'.split()
 
             user = dict(zip(paramNames, params))
+            user['realname'].lstrip(':')
             user['cid'] = user['cid'].decode('ascii')
             user['nick'] = user['nick'].decode('ascii')
             user['modes'] = user['modes'].lstrip('+')

