Exemplo n.º 1
0
static void prplcb_blist_update( PurpleBuddyList *list, PurpleBlistNode *node )
{
	if( node->type == PURPLE_BLIST_BUDDY_NODE )
	{
		PurpleBuddy *bud = (PurpleBuddy*) node;
		PurpleGroup *group = purple_buddy_get_group( bud );
		struct im_connection *ic = purple_ic_by_pa( bud->account );
		PurpleStatus *as;
		int flags = 0;
		
		if( ic == NULL )
			return;
		
		if( bud->server_alias )
			imcb_rename_buddy( ic, bud->name, bud->server_alias );
		else if( bud->alias )
			imcb_rename_buddy( ic, bud->name, bud->alias );
		
		if( group )
			imcb_add_buddy( ic, bud->name, purple_group_get_name( group ) );
		
		flags |= purple_presence_is_online( bud->presence ) ? OPT_LOGGED_IN : 0;
		flags |= purple_presence_is_available( bud->presence ) ? 0 : OPT_AWAY;
		
		as = purple_presence_get_active_status( bud->presence );
		
		imcb_buddy_status( ic, bud->name, flags, purple_status_get_name( as ),
		                   purple_status_get_attr_string( as, "message" ) );
		
		imcb_buddy_times( ic, bud->name,
		                  purple_presence_get_login_time( bud->presence ),
		                  purple_presence_get_idle_time( bud->presence ) );
	}
}
Exemplo n.º 2
0
static void
steam_cb_friends(SteamApiReq *req, gpointer data)
{
    bee_user_t *bu;
    gchar sid[STEAM_ID_STRMAX];
    GList *l;
    SteamData *sata = data;
    SteamUser *user;
    SteamUserInfo *info;
    struct im_connection *ic = sata->ic;

    if (steam_req_error(sata, req, TRUE)) {
        return;
    }

    if (!(ic->flags & BEE_USER_ONLINE)) {
        imcb_connected(ic);
    }

    for (l = req->infs->head; l != NULL; l = l->next) {
        info = l->data;
        STEAM_ID_STR(info->id, sid);

        /* Attempt to grab the buddy before adding */
        bu = bee_user_by_handle(sata->ic->bee, sata->ic, sid);

        if (bu == NULL) {
            imcb_add_buddy(sata->ic, sid, NULL);
            imcb_buddy_nick_hint(sata->ic, sid, info->nick);
            imcb_rename_buddy(sata->ic, sid, info->fullname);
        }

        bu = bee_user_by_handle(sata->ic->bee, sata->ic, sid);

        if (G_UNLIKELY(bu == NULL)) {
            continue;
        }

        user = bu->data;
        user->vtime = info->vtime;

        switch (info->rel) {
        case STEAM_USER_REL_FRIEND:
            steam_user_status(sata, info, bu);
            break;

        case STEAM_USER_REL_IGNORE:
            ic->deny = g_slist_prepend(ic->deny, g_strdup(bu->handle));
            break;
        }

        if (info->unread > 0) {
            req = steam_api_req_new(req->api, steam_cb_msgs, sata);
            steam_api_req_msgs(req, info->id, info->vtime);
        }
    }

    req = steam_api_req_new(req->api, steam_cb_poll, sata);
    steam_api_req_poll(req);
}
Exemplo n.º 3
0
Arquivo: iq.c Projeto: shiplu/bitlbee
static xt_status jabber_parse_roster( struct im_connection *ic, struct xt_node *node, struct xt_node *orig )
{
	struct xt_node *query, *c;
	int initial = ( orig != NULL );
	
	if( !( query = xt_find_node( node->children, "query" ) ) )
	{
		imcb_log( ic, "Warning: Received NULL roster packet" );
		return XT_HANDLED;
	}
	
	c = query->children;
	while( ( c = xt_find_node( c, "item" ) ) )
	{
		struct xt_node *group = xt_find_node( c->children, "group" );
		char *jid = xt_find_attr( c, "jid" );
		char *name = xt_find_attr( c, "name" );
		char *sub = xt_find_attr( c, "subscription" );
		
		if( jid && sub )
		{
			if( ( strcmp( sub, "both" ) == 0 || strcmp( sub, "to" ) == 0 ) )
			{
				imcb_add_buddy( ic, jid, ( group && group->text_len ) ?
				                           group->text : NULL );
				
				if( name )
					imcb_rename_buddy( ic, jid, name );
			}
			else if( strcmp( sub, "remove" ) == 0 )
			{
				jabber_buddy_remove_bare( ic, jid );
				imcb_remove_buddy( ic, jid, NULL );
			}
		}
		
		c = c->next;
	}
	
	if( initial )
		imcb_connected( ic );
	
	return XT_HANDLED;
}
Exemplo n.º 4
0
/**
 * Add a buddy if it is not already added, set the status to logged in.
 */
static void twitter_add_buddy(struct im_connection *ic, char *name, const char *fullname)
{
    struct twitter_data *td = ic->proto_data;

    // Check if the buddy is already in the buddy list.
    if (!bee_user_by_handle(ic->bee, ic, name)) {
        char *mode = set_getstr(&ic->acc->set, "mode");

        // The buddy is not in the list, add the buddy and set the status to logged in.
        imcb_add_buddy(ic, name, NULL);
        imcb_rename_buddy(ic, name, fullname);
        if (g_strcasecmp(mode, "chat") == 0) {
            /* Necessary so that nicks always get translated to the
               exact Twitter username. */
            imcb_buddy_nick_hint(ic, name, name);
            imcb_chat_add_buddy(td->timeline_gc, name);
        } else if (g_strcasecmp(mode, "many") == 0)
            imcb_buddy_status(ic, name, OPT_LOGGED_IN, NULL, NULL);
    }
}
Exemplo n.º 5
0
/**
 * Processes a #SteamApiMsg.
 *
 * @param sata The #SteamData.
 * @param msg  The #SteamUserMsg.
 * @param time The timestamp (UTC) of the message, or 0 for now.
 **/
static void steam_user_msg(SteamData *sata, SteamUserMsg *msg, gint64 time)
{
    SteamUserInfo *info = msg->info;
    bee_user_t    *bu;
    gchar         *str;
    guint32        f;
    gchar          sid[STEAM_ID_STR_MAX];

    STEAM_ID_STR(info->id, sid);
    STEAM_UTIL_DEBUGLN("Incoming message from %s (Type: %u, Act: %u)",
                       sid, msg->type, info->act);

    switch (msg->type) {
    case STEAM_USER_MSG_TYPE_EMOTE:
    case STEAM_USER_MSG_TYPE_SAYTEXT:
        bu = imcb_buddy_by_handle(sata->ic, sid);

        if ((bu != NULL) && (bu->flags & OPT_TYPING))
            imcb_buddy_typing(sata->ic, sid, 0);

        if (msg->type == STEAM_USER_MSG_TYPE_EMOTE)
            str = g_strconcat("/me ", msg->text, NULL);
        else
            str = g_strdup(msg->text);

        imcb_buddy_msg(sata->ic, sid, str, 0, time);
        g_free(str);
        return;

    case STEAM_USER_MSG_TYPE_LEFT_CONV:
        imcb_buddy_typing(sata->ic, sid, 0);
        return;

    case STEAM_USER_MSG_TYPE_RELATIONSHIP:
        goto relationship;

    case STEAM_USER_MSG_TYPE_TYPING:
        bu = imcb_buddy_by_handle(sata->ic, sid);

        if (G_UNLIKELY(bu == NULL))
            return;

        f = (bu->flags & OPT_TYPING) ? 0 : OPT_TYPING;
        imcb_buddy_typing(sata->ic, sid, f);
        return;

    default:
        steam_user_status(sata, info, NULL);
        return;
    }

relationship:
    switch (info->act) {
    case STEAM_USER_ACT_REMOVE:
    case STEAM_USER_ACT_IGNORE:
        imcb_remove_buddy(sata->ic, sid, NULL);
        return;

    case STEAM_USER_ACT_REQUEST:
        imcb_ask_auth(sata->ic, sid, info->nick);
        return;

    case STEAM_USER_ACT_ADD:
        imcb_add_buddy(sata->ic, sid, NULL);
        imcb_buddy_nick_hint(sata->ic, sid, info->nick);
        imcb_rename_buddy(sata->ic, sid, info->fullname);
        steam_user_status(sata, info, NULL);
        return;

    default:
        return;
    }
}
Exemplo n.º 6
0
static void skype_parse_user(struct im_connection *ic, char *line)
{
	int flags = 0;
	char *ptr;
	struct skype_data *sd = ic->proto_data;
	char *user = strchr(line, ' ');
	char *status = strrchr(line, ' ');

	status++;
	ptr = strchr(++user, ' ');
	if (!ptr)
		return;
	*ptr = '\0';
	ptr++;
	if (!strncmp(ptr, "ONLINESTATUS ", 13)) {
		if (!strlen(user) || !strcmp(user, sd->username))
			return;
		if (!set_getbool(&ic->acc->set, "test_join")
				&& !strcmp(user, "echo123"))
			return;
		ptr = g_strdup_printf("*****@*****.**", user);
		imcb_add_buddy(ic, ptr, skype_group_by_username(ic, user));
		if (strcmp(status, "OFFLINE") && (strcmp(status, "SKYPEOUT") ||
			!set_getbool(&ic->acc->set, "skypeout_offline")))
			flags |= OPT_LOGGED_IN;
		if (strcmp(status, "ONLINE") && strcmp(status, "SKYPEME"))
			flags |= OPT_AWAY;
		imcb_buddy_status(ic, ptr, flags, NULL, NULL);
		g_free(ptr);
	} else if (!strncmp(ptr, "RECEIVEDAUTHREQUEST ", 20)) {
		char *message = ptr + 20;
		if (strlen(message))
			skype_buddy_ask(ic, user, message);
	} else if (!strncmp(ptr, "BUDDYSTATUS ", 12)) {
		char *st = ptr + 12;
		if (!strcmp(st, "3")) {
			char *buf = g_strdup_printf("*****@*****.**", user);
			imcb_add_buddy(ic, buf, skype_group_by_username(ic, user));
			g_free(buf);
		}
	} else if (!strncmp(ptr, "MOOD_TEXT ", 10)) {
		char *buf = g_strdup_printf("*****@*****.**", user);
		bee_user_t *bu = bee_user_by_handle(ic->bee, ic, buf);
		g_free(buf);
		buf = ptr + 10;
		if (bu)
			imcb_buddy_status(ic, bu->handle, bu->flags, NULL,
					*buf ? buf : NULL);
		if (set_getbool(&ic->acc->set, "show_moods"))
			imcb_log(ic, "User `%s' changed mood text to `%s'", user, buf);
	} else if (!strncmp(ptr, "FULLNAME ", 9)) {
		char *name = ptr + 9;
		if (sd->is_info) {
			sd->is_info = FALSE;
			sd->info_fullname = g_strdup(name);
		} else {
			char *buf = g_strdup_printf("*****@*****.**", user);
			imcb_rename_buddy(ic, buf, name);
			g_free(buf);
		}
	} else if (!strncmp(ptr, "PHONE_HOME ", 11))
		sd->info_phonehome = g_strdup(ptr + 11);
	else if (!strncmp(ptr, "PHONE_OFFICE ", 13))
		sd->info_phoneoffice = g_strdup(ptr + 13);
	else if (!strncmp(ptr, "PHONE_MOBILE ", 13))
		sd->info_phonemobile = g_strdup(ptr + 13);
	else if (!strncmp(ptr, "NROF_AUTHED_BUDDIES ", 20))
		sd->info_nrbuddies = g_strdup(ptr + 20);
	else if (!strncmp(ptr, "TIMEZONE ", 9))
		sd->info_tz = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "LASTONLINETIMESTAMP ", 20))
		sd->info_seen = g_strdup(ptr + 20);
	else if (!strncmp(ptr, "SEX ", 4))
		sd->info_sex = g_strdup(ptr + 4);
	else if (!strncmp(ptr, "LANGUAGE ", 9))
		sd->info_language = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "COUNTRY ", 8))
		sd->info_country = g_strdup(ptr + 8);
	else if (!strncmp(ptr, "PROVINCE ", 9))
		sd->info_province = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "CITY ", 5))
		sd->info_city = g_strdup(ptr + 5);
	else if (!strncmp(ptr, "HOMEPAGE ", 9))
		sd->info_homepage = g_strdup(ptr + 9);
	else if (!strncmp(ptr, "ABOUT ", 6)) {
		/* Support multiple about lines. */
		if (!sd->info_about)
			sd->info_about = g_strdup(ptr + 6);
		else {
			GString *st = g_string_new(sd->info_about);
			g_string_append_printf(st, "\n%s", ptr + 6);
			g_free(sd->info_about);
			sd->info_about = g_strdup(st->str);
			g_string_free(st, TRUE);
		}
	} else if (!strncmp(ptr, "BIRTHDAY ", 9)) {
		sd->info_birthday = g_strdup(ptr + 9);

		GString *st = g_string_new("Contact Information\n");
		g_string_append_printf(st, "Skype Name: %s\n", user);
		if (sd->info_fullname) {
			if (strlen(sd->info_fullname))
				g_string_append_printf(st, "Full Name: %s\n",
					sd->info_fullname);
			g_free(sd->info_fullname);
			sd->info_fullname = NULL;
		}
		if (sd->info_phonehome) {
			if (strlen(sd->info_phonehome))
				g_string_append_printf(st, "Home Phone: %s\n",
					sd->info_phonehome);
			g_free(sd->info_phonehome);
			sd->info_phonehome = NULL;
		}
		if (sd->info_phoneoffice) {
			if (strlen(sd->info_phoneoffice))
				g_string_append_printf(st, "Office Phone: %s\n",
					sd->info_phoneoffice);
			g_free(sd->info_phoneoffice);
			sd->info_phoneoffice = NULL;
		}
		if (sd->info_phonemobile) {
			if (strlen(sd->info_phonemobile))
				g_string_append_printf(st, "Mobile Phone: %s\n",
					sd->info_phonemobile);
			g_free(sd->info_phonemobile);
			sd->info_phonemobile = NULL;
		}
		g_string_append_printf(st, "Personal Information\n");
		if (sd->info_nrbuddies) {
			if (strlen(sd->info_nrbuddies))
				g_string_append_printf(st,
					"Contacts: %s\n", sd->info_nrbuddies);
			g_free(sd->info_nrbuddies);
			sd->info_nrbuddies = NULL;
		}
		if (sd->info_tz) {
			if (strlen(sd->info_tz)) {
				char ib[256];
				time_t t = time(NULL);
				t += atoi(sd->info_tz)-(60*60*24);
				struct tm *gt = gmtime(&t);
				strftime(ib, 256, "%H:%M:%S", gt);
				g_string_append_printf(st,
					"Local Time: %s\n", ib);
			}
			g_free(sd->info_tz);
			sd->info_tz = NULL;
		}
		if (sd->info_seen) {
			if (strlen(sd->info_seen)) {
				char ib[256];
				time_t it = atoi(sd->info_seen);
				struct tm *tm = localtime(&it);
				strftime(ib, 256, ("%Y. %m. %d. %H:%M"), tm);
				g_string_append_printf(st,
					"Last Seen: %s\n", ib);
			}
			g_free(sd->info_seen);
			sd->info_seen = NULL;
		}
		if (sd->info_birthday) {
			if (strlen(sd->info_birthday) &&
				strcmp(sd->info_birthday, "0")) {
				char ib[256];
				struct tm tm;
				strptime(sd->info_birthday, "%Y%m%d", &tm);
				strftime(ib, 256, "%B %d, %Y", &tm);
				g_string_append_printf(st,
					"Birthday: %s\n", ib);

				strftime(ib, 256, "%Y", &tm);
				int year = atoi(ib);
				time_t t = time(NULL);
				struct tm *lt = localtime(&t);
				g_string_append_printf(st,
					"Age: %d\n", lt->tm_year+1900-year);
			}
			g_free(sd->info_birthday);
			sd->info_birthday = NULL;
		}
		if (sd->info_sex) {
			if (strlen(sd->info_sex)) {
				char *iptr = sd->info_sex;
				while (*iptr++)
					*iptr = tolower(*iptr);
				g_string_append_printf(st,
					"Gender: %s\n", sd->info_sex);
			}
			g_free(sd->info_sex);
			sd->info_sex = NULL;
		}
		if (sd->info_language) {
			if (strlen(sd->info_language)) {
				char *iptr = strchr(sd->info_language, ' ');
				if (iptr)
					iptr++;
				else
					iptr = sd->info_language;
				g_string_append_printf(st,
					"Language: %s\n", iptr);
			}
			g_free(sd->info_language);
			sd->info_language = NULL;
		}
		if (sd->info_country) {
			if (strlen(sd->info_country)) {
				char *iptr = strchr(sd->info_country, ' ');
				if (iptr)
					iptr++;
				else
					iptr = sd->info_country;
				g_string_append_printf(st,
					"Country: %s\n", iptr);
			}
			g_free(sd->info_country);
			sd->info_country = NULL;
		}
		if (sd->info_province) {
			if (strlen(sd->info_province))
				g_string_append_printf(st,
					"Region: %s\n", sd->info_province);
			g_free(sd->info_province);
			sd->info_province = NULL;
		}
		if (sd->info_city) {
			if (strlen(sd->info_city))
				g_string_append_printf(st,
					"City: %s\n", sd->info_city);
			g_free(sd->info_city);
			sd->info_city = NULL;
		}
		if (sd->info_homepage) {
			if (strlen(sd->info_homepage))
				g_string_append_printf(st,
					"Homepage: %s\n", sd->info_homepage);
			g_free(sd->info_homepage);
			sd->info_homepage = NULL;
		}
		if (sd->info_about) {
			if (strlen(sd->info_about))
				g_string_append_printf(st, "%s\n",
					sd->info_about);
			g_free(sd->info_about);
			sd->info_about = NULL;
		}
		imcb_log(ic, "%s", st->str);
		g_string_free(st, TRUE);
	}
}
Exemplo n.º 7
0
static int msn_ns_command( struct msn_handler_data *handler, char **cmd, int num_parts )
{
	struct im_connection *ic = handler->data;
	struct msn_data *md = ic->proto_data;
	
	if( num_parts == 0 )
	{
		/* Hrrm... Empty command...? Ignore? */
		return( 1 );
	}
	
	if( strcmp( cmd[0], "VER" ) == 0 )
	{
		if( cmd[2] && strncmp( cmd[2], MSNP_VER, 5 ) != 0 )
		{
			imcb_error( ic, "Unsupported protocol" );
			imc_logout( ic, FALSE );
			return( 0 );
		}
		
		return( msn_ns_write( ic, handler->fd, "CVR %d 0x0409 mac 10.2.0 ppc macmsgs 3.5.1 macmsgs %s\r\n",
		                      ++md->trId, ic->acc->user ) );
	}
	else if( strcmp( cmd[0], "CVR" ) == 0 )
	{
		/* We don't give a damn about the information we just received */
		return msn_ns_write( ic, handler->fd, "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user );
	}
	else if( strcmp( cmd[0], "XFR" ) == 0 )
	{
		char *server;
		int port;
		
		if( num_parts >= 6 && strcmp( cmd[2], "NS" ) == 0 )
		{
			b_event_remove( handler->inpa );
			handler->inpa = -1;
			
			server = strchr( cmd[3], ':' );
			if( !server )
			{
				imcb_error( ic, "Syntax error" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			*server = 0;
			port = atoi( server + 1 );
			server = cmd[3];
			
			imcb_log( ic, "Transferring to other server" );
			return msn_ns_connect( ic, handler, server, port );
		}
		else if( num_parts >= 6 && strcmp( cmd[2], "SB" ) == 0 )
		{
			struct msn_switchboard *sb;
			
			server = strchr( cmd[3], ':' );
			if( !server )
			{
				imcb_error( ic, "Syntax error" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			*server = 0;
			port = atoi( server + 1 );
			server = cmd[3];
			
			if( strcmp( cmd[4], "CKI" ) != 0 )
			{
				imcb_error( ic, "Unknown authentication method for switchboard" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			
			debug( "Connecting to a new switchboard with key %s", cmd[5] );

			if( ( sb = msn_sb_create( ic, server, port, cmd[5], MSN_SB_NEW ) ) == NULL )
			{
				/* Although this isn't strictly fatal for the NS connection, it's
				   definitely something serious (we ran out of file descriptors?). */
				imcb_error( ic, "Could not create new switchboard" );
				imc_logout( ic, TRUE );
				return( 0 );
			}
			
			if( md->msgq )
			{
				struct msn_message *m = md->msgq->data;
				GSList *l;
				
				sb->who = g_strdup( m->who );
				
				/* Move all the messages to the first user in the message
				   queue to the switchboard message queue. */
				l = md->msgq;
				while( l )
				{
					m = l->data;
					l = l->next;
					if( strcmp( m->who, sb->who ) == 0 )
					{
						sb->msgq = g_slist_append( sb->msgq, m );
						md->msgq = g_slist_remove( md->msgq, m );
					}
				}
			}
		}
		else
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "USR" ) == 0 )
	{
		if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 &&
		    strcmp( cmd[3], "S" ) == 0 )
		{
			g_free( md->pp_policy );
			md->pp_policy = g_strdup( cmd[4] );
			msn_soap_passport_sso_request( ic, cmd[5] );
		}
		else if( strcmp( cmd[2], "OK" ) == 0 )
		{
			/* If the number after the handle is 0, the e-mail
			   address is unverified, which means we can't change
			   the display name. */
			if( cmd[4][0] == '0' )
				md->flags |= MSN_EMAIL_UNVERIFIED;
			
			imcb_log( ic, "Authenticated, getting buddy list" );
			msn_soap_memlist_request( ic );
		}
		else
		{
			imcb_error( ic, "Unknown authentication type" );
			imc_logout( ic, FALSE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "MSG" ) == 0 )
	{
		if( num_parts < 4 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		handler->msglen = atoi( cmd[3] );
		
		if( handler->msglen <= 0 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
	else if( strcmp( cmd[0], "BLP" ) == 0 )
	{
		msn_ns_send_adl_start( ic );
		return msn_ns_finish_login( ic );
	}
	else if( strcmp( cmd[0], "ADL" ) == 0 )
	{
		if( num_parts >= 3 && strcmp( cmd[2], "OK" ) == 0 )
		{
			msn_ns_send_adl( ic );
			return msn_ns_finish_login( ic );
		}
		else if( num_parts >= 3 )
		{
			handler->msglen = atoi( cmd[2] );
		}
	}
	else if( strcmp( cmd[0], "PRP" ) == 0 )
	{
		imcb_connected( ic );
	}
	else if( strcmp( cmd[0], "CHL" ) == 0 )
	{
		char *resp;
		int st;
		
		if( num_parts < 3 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		resp = msn_p11_challenge( cmd[2] );
		
		st =  msn_ns_write( ic, -1, "QRY %d %s %zd\r\n%s",
		                    ++md->trId, MSNP11_PROD_ID,
		                    strlen( resp ), resp );
		g_free( resp );
		return st;
	}
	else if( strcmp( cmd[0], "ILN" ) == 0 || strcmp( cmd[0], "NLN" ) == 0 )
	{
		const struct msn_away_state *st;
		const char *handle;
		int cap = 0;
		
		if( num_parts < 6 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		/* ILN and NLN are more or less the same, except ILN has a trId
		   at the start, and NLN has a capability field at the end. 
		   Does ILN still exist BTW? */
		if( cmd[0][1] == 'I' )
			cmd ++;
		else
			cap = atoi( cmd[4] );

		handle = msn_normalize_handle( cmd[2] );
		if( strcmp( handle, ic->acc->user ) == 0 )
			return 1; /* That's me! */
		
		http_decode( cmd[3] );
		imcb_rename_buddy( ic, handle, cmd[3] );
		
		st = msn_away_state_by_code( cmd[1] );
		if( !st )
		{
			/* FIXME: Warn/Bomb about unknown away state? */
			st = msn_away_state_list + 1;
		}
		
		imcb_buddy_status( ic, handle, OPT_LOGGED_IN | 
		                   ( st != msn_away_state_list ? OPT_AWAY : 0 ) |
		                   ( cap & 1 ? OPT_MOBILE : 0 ),
		                   st->name, NULL );
		
		msn_sb_stop_keepalives( msn_sb_by_handle( ic, handle ) );
	}
	else if( strcmp( cmd[0], "FLN" ) == 0 )
	{
		const char *handle;
		
		if( cmd[1] == NULL )
			return 1;
		
		handle = msn_normalize_handle( cmd[1] );
		imcb_buddy_status( ic, handle, 0, NULL, NULL );
		msn_sb_start_keepalives( msn_sb_by_handle( ic, handle ), TRUE );
	}
	else if( strcmp( cmd[0], "RNG" ) == 0 )
	{
		struct msn_switchboard *sb;
		char *server;
		int session, port;
		
		if( num_parts < 7 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		session = atoi( cmd[1] );
		
		server = strchr( cmd[2], ':' );
		if( !server )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		*server = 0;
		port = atoi( server + 1 );
		server = cmd[2];
		
		if( strcmp( cmd[3], "CKI" ) != 0 )
		{
			imcb_error( ic, "Unknown authentication method for switchboard" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		
		debug( "Got a call from %s (session %d). Key = %s", cmd[5], session, cmd[4] );
		
		if( ( sb = msn_sb_create( ic, server, port, cmd[4], session ) ) == NULL )
		{
			/* Although this isn't strictly fatal for the NS connection, it's
			   definitely something serious (we ran out of file descriptors?). */
			imcb_error( ic, "Could not create new switchboard" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
		else
		{
			sb->who = g_strdup( msn_normalize_handle( cmd[5] ) );
		}
	}
	else if( strcmp( cmd[0], "OUT" ) == 0 )
	{
		int allow_reconnect = TRUE;
		
		if( cmd[1] && strcmp( cmd[1], "OTH" ) == 0 )
		{
			imcb_error( ic, "Someone else logged in with your account" );
			allow_reconnect = FALSE;
		}
		else if( cmd[1] && strcmp( cmd[1], "SSD" ) == 0 )
		{
			imcb_error( ic, "Terminating session because of server shutdown" );
		}
		else
		{
			imcb_error( ic, "Session terminated by remote server (%s)",
			            cmd[1] ? cmd[1] : "reason unknown)" );
		}
		
		imc_logout( ic, allow_reconnect );
		return( 0 );
	}
	else if( strcmp( cmd[0], "IPG" ) == 0 )
	{
		imcb_error( ic, "Received IPG command, we don't handle them yet." );
		
		handler->msglen = atoi( cmd[1] );
		
		if( handler->msglen <= 0 )
		{
			imcb_error( ic, "Syntax error" );
			imc_logout( ic, TRUE );
			return( 0 );
		}
	}
#if 0
	else if( strcmp( cmd[0], "ADG" ) == 0 )
	{
		char *group = g_strdup( cmd[3] );
		int groupnum, i;
		GSList *l, *next;
		
		http_decode( group );
		if( sscanf( cmd[4], "%d", &groupnum ) == 1 )
		{
			if( groupnum >= md->groupcount )
			{
				md->grouplist = g_renew( char *, md->grouplist, groupnum + 1 );
				for( i = md->groupcount; i <= groupnum; i ++ )
					md->grouplist[i] = NULL;
				md->groupcount = groupnum + 1;
			}
			g_free( md->grouplist[groupnum] );
			md->grouplist[groupnum] = group;
		}