예제 #1
0
static void om_login(PurpleAccount *account)
{
	PurpleBuddy *bud;
	OmegleAccount *oma;
	
	//make sure there's an Omegle buddy on the buddy list
	bud = purple_find_buddy(account, "omegle");
	if (bud == NULL)
	{
		bud = purple_buddy_new(account, "omegle", "Omegle");
		purple_blist_add_buddy(bud, NULL, NULL, NULL);
	}
	purple_prpl_got_user_status(account, "omegle", purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
	
	
	oma = g_new0(OmegleAccount, 1);
	oma->account = account;
	oma->pc = purple_account_get_connection(account);
	oma->cookie_table = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, g_free);
	oma->hostname_ip_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, g_free);
	account->gc->proto_data = oma;
	
	//No such thing as a login
	purple_connection_set_state(purple_account_get_connection(account), PURPLE_CONNECTED);
	
}
예제 #2
0
파일: fb_blist.c 프로젝트: bf4/pidgin-mac
static void set_buddies_offline(PurpleBuddy *buddy, GSList *online_buddies_list)
{
    if (g_slist_find(online_buddies_list, buddy) == NULL &&
            PURPLE_BUDDY_IS_ONLINE(buddy))
    {
        purple_prpl_got_user_status(buddy->account, buddy->name,
                                    purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE),
                                    NULL);
    }
}
예제 #3
0
void
pb_add_buddy_with_invite(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char* message)
{
	PushBulletAccount *pba = pc->proto_data;
	const gchar *contacts_url = "https://api.pushbullet.com/v2/contacts";
	GString *postdata;
	const gchar *buddy_name;
	
	buddy_name = purple_buddy_get_name(buddy);
	if (!PB_IS_SMS(buddy_name)) {
		postdata = g_string_new(NULL);
		g_string_append_printf(postdata, "name=%s", purple_url_encode(purple_buddy_get_alias(buddy)));
		g_string_append_printf(postdata, "email=%s", purple_url_encode(buddy_name));
		
		pb_fetch_url(pba, contacts_url, postdata->str, NULL, NULL);
		
		g_string_free(postdata, TRUE);
		purple_prpl_got_user_status(pba->account, buddy_name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
	} else {
		
		purple_prpl_got_user_status(pba->account, buddy_name, "mobile", NULL);
		purple_prpl_got_user_status(pba->account, buddy_name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
	}
}
예제 #4
0
static void
pb_got_phonebook(PushBulletAccount *pba, JsonNode *node, gpointer user_data)
{
	PurpleAccount *account = pba->account;
	JsonObject *rootobj = json_node_get_object(node);
	JsonArray *phonebook = json_object_get_array_member(rootobj, "phonebook");
	gint i;
	guint len;
	gchar *device = user_data;
	PurpleGroup *pbgroup;
	
	pbgroup = purple_find_group("PushBullet");
	if (!pbgroup)
	{
		pbgroup = purple_group_new("PushBullet");
		purple_blist_add_group(pbgroup, NULL);
	}
	
	for(i = 0, len = json_array_get_length(phonebook); i < len; i++)
	{
		JsonObject *number = json_array_get_object_element(phonebook, i);
		const gchar *name = json_object_get_string_member(number, "name");
		const gchar *phone = json_object_get_string_member(number, "phone");
		const gchar *phone_type = json_object_get_string_member(number, "phone_type");
		PurpleBuddy *pbuddy;
		
		//Only handle the right 'type' of phone number. 
		//home, mobile, work, other
		if (purple_account_get_bool(account, "mobile_contacts_only", FALSE) && phone_type[0] != 'm')
			continue;
		
		pbuddy = purple_find_buddy(account, phone);
		if (!pbuddy)
		{
			pbuddy = purple_buddy_new(account, phone, name);
			purple_blist_add_buddy(pbuddy, NULL, pbgroup, NULL);
			purple_debug_info("pushbullet", "Added buddy %s %s\n", phone, name);
		}
		
		purple_prpl_got_user_status(account, phone, "mobile", NULL);
		purple_prpl_got_user_status(account, phone, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
	}
	
	g_free(device);
}
예제 #5
0
static PurpleStatus *quetzal_get_correct_status(PurplePresence *presence, Status qutim_status)
{
	PurpleStatus *status = NULL;

	PurpleStatusPrimitive type;
	switch (qutim_status.type()) {
	case Status::Online:
		type = PURPLE_STATUS_AVAILABLE;
		break;
	case Status::FreeChat:
		if ((status = purple_presence_get_status(presence, "freeforchat"))
			|| (status = purple_presence_get_status(presence, "free4chat")))
			return status;
		type = PURPLE_STATUS_AVAILABLE;
		break;
	case Status::Away:
		type = PURPLE_STATUS_AWAY;
		break;
	case Status::NA:
		type = PURPLE_STATUS_EXTENDED_AWAY;
		break;
	case Status::DND:
		if (!!(status = purple_presence_get_status(presence, "dnd")))
			return status;
		type = PURPLE_STATUS_UNAVAILABLE;
		break;
	case Status::Invisible:
		type = PURPLE_STATUS_INVISIBLE;
		break;
	case Status::Offline:
		type = PURPLE_STATUS_OFFLINE;
		break;
	default:
		type = PURPLE_STATUS_UNSET;
		break;
	}

	return purple_presence_get_status(presence, purple_primitive_get_id_from_type(type));
}
예제 #6
0
파일: im.cpp 프로젝트: jasuarez/minbif
bool IM::setStatus(string away)
{
	PurpleStatusPrimitive prim = PURPLE_STATUS_AVAILABLE;
	if(away.empty() == false)
	{
		string s = strlower(away);
		int i;
		/* Looking for an existant status equivalent to the away message. */
		for(i = 0;
		    (
		      i < PURPLE_STATUS_NUM_PRIMITIVES &&
		      strlower(purple_primitive_get_name_from_type((PurpleStatusPrimitive)i)) != s &&
		      purple_primitive_get_id_from_type((PurpleStatusPrimitive)i) != s
		    );
		    ++i)
			;

		if(i >= PURPLE_STATUS_NUM_PRIMITIVES)
		{
			/* If the status does not exist, set the AWAY status and set the message
			 * given in the \b away string as the status message. */
			prim = PURPLE_STATUS_AWAY;
		}
		else
		{
			prim = (PurpleStatusPrimitive)i;
			away.clear(); /* do not change the saved status message. */
		}
	}

	map<string, Account> alist = getAccountsList();
	for(map<string, Account>::iterator it = alist.begin(); it != alist.end(); ++it)
		it->second.setStatus(prim, away);

	return true;
}
static void received_im_msg_cb(PurpleAccount *account, char *who, char *buffer,
    PurpleConversation *conv, PurpleMessageFlags flags, void *data) {
    // A workaround to avoid skipping of the first message as a result on NULL-conv:
    if (conv == NULL) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
        account, who); 
    PurpleBuddy *buddy = purple_find_buddy(account, who);
    PurplePresence *presence = purple_buddy_get_presence(buddy);
    msg_metadata_t msg;

    //Get message
    msg.text = purple_markup_strip_html(buffer);
    msg.remote_username = who;

    //LOCAL USER:
    msg.local_alias = purple_account_get_alias(account);
    msg.local_username = (char *) purple_account_get_name_for_display(account);

    //REMOTE USER (Buddy):
    //Get buddy alias
    msg.remote_alias = purple_buddy_get_alias(buddy);
    if(msg.remote_alias == NULL) msg.remote_alias = "";

    //Get buddy group
    PurpleGroup *group = purple_buddy_get_group(buddy);
    //return empty string if not in group
    msg.remote_from_group = group != NULL ? purple_group_get_name(group) : ""; 

    //Get protocol ID
    msg.protocol_id = purple_account_get_protocol_id(account);
    //trim out PROTOCOL_PREFIX (eg.: "prpl-irc" => "irc")
    if(!strncmp(msg.protocol_id,PROTOCOL_PREFIX,strlen(PROTOCOL_PREFIX))) 
        msg.protocol_id += strlen(PROTOCOL_PREFIX); 

    //Get status
    PurpleStatus *status = purple_account_get_active_status(account);
    PurpleStatusType *type = purple_status_get_type(status);
    //remote
    PurpleStatus *r_status = purple_presence_get_active_status(presence);
    PurpleStatusType *r_status_type =	purple_status_get_type(r_status);

    //Get status id
    msg.local_status_id = NULL;
    msg.local_status_id = purple_primitive_get_id_from_type(
        purple_status_type_get_primitive(type));
    //remote
    msg.remote_status_id = NULL;
    msg.remote_status_id = purple_primitive_get_id_from_type(
        purple_status_type_get_primitive(r_status_type));

    //Get status message
    msg.local_status_msg = NULL;
    if (purple_status_type_get_attr(type, "message") != NULL) {
        msg.local_status_msg = purple_status_get_attr_string(status, "message");
    } else {
        PurpleSavedStatus *savedstatus = purple_savedstatus_get_current();
        if(savedstatus)
            msg.local_status_msg = purple_savedstatus_get_message(savedstatus);
    }
    //remote
    msg.remote_status_msg = NULL;
    if (purple_status_type_get_attr(r_status_type, "message") != NULL) {
        msg.remote_status_msg = purple_status_get_attr_string(r_status, "message");
    } else {
        msg.remote_status_msg = "";
    }

    run_lua(conv, msg);
}
예제 #8
0
static void
pb_got_everything(PushBulletAccount *pba, JsonNode *node, gpointer user_data)
{
	JsonObject *rootobj = json_node_get_object(node);
	JsonArray *devices = json_object_has_member(rootobj, "devices") ? json_object_get_array_member(rootobj, "devices") : NULL;
	JsonArray *pushes = json_object_has_member(rootobj, "pushes") ? json_object_get_array_member(rootobj, "pushes") : NULL;
	JsonArray *contacts = json_object_has_member(rootobj, "contacts") ? json_object_get_array_member(rootobj, "contacts") : NULL;
	JsonArray *chats = json_object_has_member(rootobj, "chats") ? json_object_get_array_member(rootobj, "chats") : NULL;
	JsonArray *texts = json_object_has_member(rootobj, "texts") ? json_object_get_array_member(rootobj, "texts") : NULL;
	gint i;
	guint len;
	PurpleGroup *pbgroup;
	
	pbgroup = purple_find_group("PushBullet");
	if (!pbgroup)
	{
		pbgroup = purple_group_new("PushBullet");
		purple_blist_add_group(pbgroup, NULL);
	}
	
	if (json_object_has_member(rootobj, "error")) {
		JsonObject *error = json_object_get_object_member(rootobj, "error");
		const gchar *type = json_object_get_string_member(error, "type");
		const gchar *message = json_object_get_string_member(error, "message");
		
		//TODO check type
		purple_connection_error_reason(pba->pc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, message);
		return;
	}
	
	if (devices != NULL) {
		for(i = 0, len = json_array_get_length(devices); i < len; i++) {
			JsonObject *device = json_array_get_object_element(devices, i);
			
			if (pba->main_sms_device == NULL && json_object_get_boolean_member(device, "has_sms")) {
				pba->main_sms_device = g_strdup(json_object_get_string_member(device, "iden"));
				purple_account_set_string(pba->account, "main_sms_device", pba->main_sms_device);
				
				pb_get_phonebook(pba, pba->main_sms_device);
				
				if (!pba->websocket) {
					pb_start_polling(pba);
				}
				
				break; //TODO handle more than one
			}
		}
	}
	
	if (pushes != NULL) {
		gint last_message_timestamp = purple_account_get_int(pba->account, "last_message_timestamp", 0);
		for(i = json_array_get_length(pushes); i > 0; i--) {
			JsonObject *push = json_array_get_object_element(pushes, i - 1);
			const gchar *type = json_object_get_string_member(push, "type");
			gdouble modified;
			time_t timestamp;
			gboolean dismissed;
			
			if (!type)
				continue;
			
			modified = json_object_get_double_member(push, "modified");
			timestamp = (time_t) modified;
			dismissed = json_object_get_boolean_member(push, "dismissed");
			
			if (timestamp <= last_message_timestamp || dismissed) {
				continue;
			}
			
			// {"active":true,"iden":"uffvytgsjApuAUIFRk","created":1.438895081423904e+09,"modified":1.438895081432786e+09,"type":"file","dismissed":false,"guid":"153b70f0-f7a6-4db9-a6f4-28b99fa416f1","direction":"self","sender_iden":"uffvytg","sender_email":"*****@*****.**","sender_email_normalized":"*****@*****.**","sender_name":"Eion Robb","receiver_iden":"uffvytg","receiver_email":"*****@*****.**","receiver_email_normalized":"*****@*****.**","target_device_iden":"uffvytgsjz7O3P0Jl6","source_device_iden":"uffvytgsjAoIRwhIL6","file_name":"IMG_20150807_084618.jpg","file_type":"image/jpeg","file_url":"https://dl.pushbulletusercontent.com/FHOZdyzfvnoYZY0DP6oK1rGKiJpWCPc0/IMG_20150807_084618.jpg","image_width":4128,"image_height":2322,"image_url":"https://lh3.googleusercontent.com/WY5TK7h3mzD32qMcnxtqt-4PrYcWW1uWDHnRW2x1oJK8mnYk2v4HbZrRjIQkiYdxMKQSdNI8GGPqfO6s6tEyuRVLzeA"}
			
			if (purple_strequal(type, "note") || purple_strequal(type, "link") || purple_strequal(type, "file")) {
				const gchar *from = json_object_get_string_member(push, "sender_email_normalized");
				const gchar *body = json_object_get_string_member(push, "body");
				const gchar *direction = json_object_get_string_member(push, "direction");
				gchar *body_html;
				
				if (from == NULL) {
					if (!json_object_has_member(push, "sender_name")) {
						purple_debug_error("pushbullet", "no sender name/email\n");
						continue;
					}
					from = json_object_get_string_member(push, "sender_name");
				}
				
				if (body && *body) {
					body_html = purple_strdup_withhtml(body);
				} else {
					const gchar *title = json_object_get_string_member(push, "title");
					if (title && *title) {
						body_html = purple_strdup_withhtml(title);
					} else {
						body_html = "Message";
					}
				}
				
				if (json_object_has_member(push, "url")) {
					gchar *body_with_link = g_strconcat("<a href=\"", json_object_get_string_member(push, "url"), "\">", body_html, "</a>", NULL);
					g_free(body_html);
					body_html = body_with_link;
					
				} else if (json_object_has_member(push, "image_url")) {
					const gchar *image_url = json_object_get_string_member(push, "image_url");
					PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, pba->account);
					
					if (conv == NULL)
					{
						conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, pba->account, from);
					}
					pb_download_image_to_conv(image_url, conv);
					
				} else if (json_object_has_member(push, "file_url")) {
					gchar *body_with_link;
					const gchar *file_name = json_object_get_string_member(push, "file_name");
					
					if (file_name && *file_name) {
						g_free(body_html);
						body_html = purple_strdup_withhtml(file_name);
					}
					
					body_with_link= g_strconcat("<a href=\"", json_object_get_string_member(push, "file_url"), "\">", json_object_get_string_member(push, "file_name"), "</a>", NULL);
					g_free(body_html);
					body_html = body_with_link;
				}
				
				if (direction[0] != 'o') {
					serv_got_im(pba->pc, from, body_html, PURPLE_MESSAGE_RECV, timestamp);
				} else {
					const gchar *guid = json_object_get_string_member(push, "guid");
					from = json_object_get_string_member(push, "receiver_email_normalized");
					
					if (!guid || !g_hash_table_remove(pba->sent_messages_hash, guid)) {
						PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, pba->account);
						if (conv == NULL)
						{
							conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, pba->account, from);
						}
						purple_conversation_write(conv, from, body_html, PURPLE_MESSAGE_SEND, timestamp);
					}
				}
				
				g_free(body_html);
			}
				
			purple_account_set_int(pba->account, "last_message_timestamp", MAX(purple_account_get_int(pba->account, "last_message_timestamp", 0), timestamp));
		}
	}
	
	if (contacts != NULL) {
		for(i = 0, len = json_array_get_length(contacts); i < len; i++) {
			JsonObject *contact = json_array_get_object_element(contacts, i);
			const gchar *email = json_object_get_string_member(contact, "email_normalized");
			const gchar *name = json_object_get_string_member(contact, "name");
			const gchar *image_url = json_object_get_string_member(contact, "image_url");
			
			PurpleBuddy *buddy = purple_find_buddy(pba->account, email);
			if (buddy == NULL)
			{
				buddy = purple_buddy_new(pba->account, email, name);
				purple_blist_add_buddy(buddy, NULL, pbgroup, NULL);
			}
			purple_prpl_got_user_status(pba->account, email, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
		}
	}
	
	if (chats != NULL) {
		for(i = 0, len = json_array_get_length(chats); i < len; i++) {
			JsonObject *chat = json_array_get_object_element(chats, i);
			JsonObject *contact = json_object_get_object_member(chat, "with");
			const gchar *email = json_object_get_string_member(contact, "email_normalized");
			const gchar *name = json_object_get_string_member(contact, "name");
			const gchar *image_url = json_object_get_string_member(contact, "image_url");
			
			PurpleBuddy *buddy = purple_find_buddy(pba->account, email);
			if (buddy == NULL)
			{
				buddy = purple_buddy_new(pba->account, email, name);
				purple_blist_add_buddy(buddy, NULL, pbgroup, NULL);
			}
			purple_prpl_got_user_status(pba->account, email, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
		}
	}
	
	if (texts != NULL) {
		for(i = 0, len = json_array_get_length(texts); i < len; i++) {
			JsonObject *text = json_array_get_object_element(texts, i);
		}
	}
}
예제 #9
0
static void parse_new_messages(PurpleConnection *pc, FacebookAccount *fba, JsonArray *messages)
{
	int i;
	PurpleBuddy *buddy;

	purple_debug_info("facebook", "parsing new messages\n");

	for (i = 0; i < json_array_get_length(messages); i++) {
		const gchar *type;
		gchar *from, *to;
		

		JsonObject *object = json_node_get_object(json_array_get_element(messages, i));
		type = json_node_get_string(json_object_get_member(object, "type"));

		from = g_strdup_printf("%" G_GINT64_FORMAT, (gint64)json_node_get_int(json_object_get_member(object, "from")));
		to = g_strdup_printf("%" G_GINT64_FORMAT, (gint64)json_node_get_int(json_object_get_member(object, "to")));
		
		/* Use the in-line buddy name if the buddy list hasn't been downloaded yet */
		buddy = purple_find_buddy(pc->account, from);
		if (buddy == NULL || buddy->server_alias == NULL || buddy->alias == NULL)
		{
			if (json_object_has_member(object, "from_name"))
			{
				const gchar *from_name = json_node_get_string(json_object_get_member(
					object, "from_name"));
				fb_blist_set_alias(fba, from, from_name);
			}
		}

		if (from && to && g_str_equal(type, "msg")) {
			JsonObject *messageObj = json_node_get_object(json_object_get_member(object, "msg"));
			parse_message(pc, fba, messageObj, from, to, PURPLE_CONV_TYPE_IM);
		} else if (from && g_str_equal(type, "typ")) {
			purple_debug_info("facebook", "handling typing notification\n");

			gint typing = json_node_get_int(json_object_get_member(object, "st"));
			if (typing == 0) {
				serv_got_typing(pc, from, 10, PURPLE_NOT_TYPING);
			} else {
				serv_got_typing(pc, from, 10, PURPLE_TYPING);
			}
		} else if (g_str_equal(type, "group_msg")) {
			PurpleConversation *conv = fb_find_chat(fba, to);
			
			if (conv != NULL)
			{			
				if (json_object_has_member(object, "to_name"))
				{
					const gchar *to_name = json_node_get_string(json_object_get_member(
						object, "to_name"));
					purple_conversation_set_title(conv, to_name);

					PurpleChat *chat = purple_blist_find_chat(fba->account, to);
					purple_blist_alias_chat(chat, to_name);
				}
				if (!purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), from))
				{
					purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), from, NULL, PURPLE_CBFLAGS_NONE, FALSE);
				}
				if (!purple_find_buddy(fba->account, from))
				{
					const char *from_name = json_node_get_string(json_object_get_member(
						object, "from_name"));
					buddy = purple_buddy_new(fba->account, from, from_name);
					purple_blist_node_set_flags((PurpleBlistNode *)buddy, PURPLE_BLIST_NODE_FLAG_NO_SAVE);
					purple_blist_add_buddy(buddy, NULL, purple_find_group(DEFAULT_GROUP_NAME), NULL);
				}
			}

			JsonObject *messageObj = json_node_get_object(json_object_get_member(object, "msg"));
			parse_message(pc, fba, messageObj, from, to, PURPLE_CONV_TYPE_CHAT);
		}

		/*
		 * we've received something from a buddy, assume they're online
		 * only if it's not from ourselves
		 */
		if (from && fba->uid != atoll(from)) {
			purple_prpl_got_user_status(
				fba->account, from, 
				purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);

		}
	
		g_free(from);
		g_free(to);

		fba->message_fetch_sequence++;
	}
}
예제 #10
0
파일: fb_blist.c 프로젝트: bf4/pidgin-mac
static void got_buddy_list_cb(FacebookAccount *fba, gchar *data,
                              gsize data_len, gpointer userdata)
{
    GSList *buddies_list;
    GSList *online_buddies_list = NULL;
    PurpleBuddy *buddy;
    FacebookBuddy *fbuddy;
    gchar *uid;
    gchar *name;
    gchar *status_text;
    gchar *status_time_text;
    gchar *buddy_icon_url;
    gboolean idle;
    guint32 error_number;

    gchar *search_start;
    gchar *search_tmp;
    gchar *tmp;
    gchar *largest_buddy_search_point = NULL;

    PurpleGroup *fb_group = NULL;

    gboolean current_buddy_online = FALSE;

    purple_debug_info("facebook", "parsing buddy list\n");
    purple_debug_misc("facebook", "buddy list\n%s\n", data);

    if (fba == NULL)
        return;

    if (data == NULL) {
        purple_connection_error_reason(fba->pc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
                                       _("Could not retrieve buddy list"));
        return;
    }

    /* Check if the facebook group already exists (fixes #13) */
    fb_group = purple_find_group("Facebook");

    /* if logged out, this comes up */
    /* for (;;);{"error":1357001,"errorSummary":"Not Logged In",
    	"errorDescription":"You must be logged in to do that.",
    	"payload":null,"bootload":[{"name":"js\/common.js.pkg.php",
    	"type":"js","src":"http:\/\/static.ak.fbcdn.net\/rsrc.php\/pkg\/59\
    	/98561\/js\/common.js.pkg.php"}]} */
    tmp = g_strstr_len(data, data_len, "\"error\":");
    if (tmp != NULL)
    {
        tmp += 9;
        tmp = g_strndup(tmp, strchr(tmp, ',')-tmp);
        error_number = atoi(tmp);
        g_free(tmp);
        if (error_number)
        {
            /* error :( */
            tmp = g_strstr_len(data, data_len, "\"errorDescription\":");
            tmp += 20;
            tmp = g_strndup(tmp, strchr(tmp, '"')-tmp);
            /* TODO: Use purple_connection_error_reason() */
            purple_connection_error(fba->pc, tmp);
            g_free(tmp);
            return;
        }
    }

    /* look for "userInfos":{ ... }, */
    search_start = strstr(data, "\"userInfos\":{");
    if (search_start == NULL)
        return;
    search_start += 13;

    while (*search_start != '}' && (search_start - data < data_len))
    {
        tmp = strchr(search_start, ':');
        uid = g_strndup(search_start+1, tmp-search_start-2);
        /* purple_debug_misc("facebook", "uid: %s\n", uid); */

        search_start += strlen(uid) + 2;

        search_tmp = strstr(search_start, "\"name\":") + 8;
        if (search_tmp > largest_buddy_search_point)
            largest_buddy_search_point = search_tmp;
        search_tmp = g_strndup(search_tmp, strchr(search_tmp, '"')-search_tmp);
        name = fb_convert_unicode(search_tmp);
        g_free(search_tmp);
        /* purple_debug_misc("facebook", "name: %s\n", name); */

        /* try updating the alias, just in case it was removed locally */
        serv_got_alias(fba->pc, uid, name);

        /* look for "uid":{"i":_____} */
        tmp = g_strdup_printf("\"%s\":{\"i\":", uid);
        search_tmp = g_strstr_len(data, data_len, tmp);
        if (search_tmp != NULL)
        {
            search_tmp += strlen(tmp);
            if (search_tmp > largest_buddy_search_point)
                largest_buddy_search_point = search_tmp;
            search_tmp = g_strndup(search_tmp, strchr(search_tmp, '}')-search_tmp);
            /* purple_debug_misc("facebook", "buddy idle: %s\n", search_tmp); */
            buddy = purple_find_buddy(fba->account, uid);
            idle = g_str_equal(search_tmp, "true");
            g_free(search_tmp);
            current_buddy_online = TRUE;
        } else {
            /* if we're here, the buddy's info has been sent, but they're not actually online */
            current_buddy_online = FALSE;
            idle = FALSE;
        }
        g_free(tmp);

        /* Set the buddy status text and time */
        search_tmp = strstr(search_start, "\"status\":");
        if (search_tmp != NULL && *(search_tmp + 9) == '"')
        {
            search_tmp += 10;
            if (search_tmp > largest_buddy_search_point)
                largest_buddy_search_point = strstr(search_tmp, ",\"statusTime");
            search_tmp = g_strndup(search_tmp, strstr(search_tmp, ",\"statusTime")-1-search_tmp);
            status_text = fb_convert_unicode(search_tmp);
            g_free(search_tmp);
        } else {
            status_text = NULL;
        }

        /* is this us? */
        if (atoi(uid) == fba->uid)
        {
            purple_connection_set_display_name(fba->pc, name);

            /* set our last known status so that we don't re-set it */
            if (status_text && !fba->last_status_message)
                fba->last_status_message = g_strdup(status_text);

            /* check that we don't want to show ourselves */
            if (purple_account_get_bool(fba->account, "facebook_hide_self", TRUE))
            {
                g_free(status_text);
                g_free(name);
                g_free(uid);

                /* Move pointer to the end of the buddy entry */
                search_start = strchr(largest_buddy_search_point, '}') + 1;
                while (*search_start == ',' && (search_start - data < data_len))
                    search_start++;
                /* go on to the next buddy */
                continue;
            } else {
                current_buddy_online = TRUE;
            }
        }

        /* Is this a new buddy? */
        buddy = purple_find_buddy(fba->account, uid);
        if (buddy == NULL)
        {
            buddy = purple_buddy_new(fba->account, uid, NULL);
            if (fb_group == NULL)
            {
                fb_group = purple_group_new("Facebook");
                purple_blist_add_group(fb_group, NULL);
            }
            purple_blist_add_buddy(buddy, NULL, fb_group, NULL);
        }
        serv_got_alias(fba->pc, uid, name);
        purple_presence_set_idle(purple_buddy_get_presence(buddy), idle, 0);

        /* Set the FacebookBuddy structure */
        if (buddy->proto_data == NULL)
        {
            fbuddy = g_new0(FacebookBuddy, 1);
            fbuddy->buddy = buddy;
            fbuddy->fba = fba;
            fbuddy->uid = atoi(uid);
            fbuddy->name = g_strdup(name);

            /* load the old buddy icon from the account settings */
            tmp = g_strdup_printf("buddy_icon_%d_cache", fbuddy->uid);
            fbuddy->thumb_url = g_strdup(purple_account_get_string(fba->account, tmp, ""));
            g_free(tmp);

            buddy->proto_data = fbuddy;
        } else {
            fbuddy = buddy->proto_data;
        }

        g_free(uid);
        g_free(name);

        if (status_text != NULL)
        {
            tmp = fb_strdup_withhtml(status_text);
            g_free(status_text);
            status_text = tmp;
            /* purple_debug_misc("facebook", "status: %s\n", status_text); */

            search_tmp = strstr(search_start, "\"statusTimeRel\":") + 17;
            if (search_tmp > largest_buddy_search_point)
                largest_buddy_search_point = strchr(search_tmp, '"');
            search_tmp = g_strndup(search_tmp, strchr(search_tmp, '"')-search_tmp);
            status_time_text = fb_convert_unicode(search_tmp);
            g_free(search_tmp);

            if (g_str_equal(status_time_text, "ull,"))
            {
                g_free(status_time_text);
                status_time_text = NULL;
            }
            g_free(fbuddy->status_rel_time);
            if (status_time_text != NULL)
            {
                fbuddy->status_rel_time = fb_strdup_withhtml(status_time_text);
                g_free(status_time_text);
                /* purple_debug_misc("facebook", "status time: %s\n", fbuddy->status_rel_time); */
            } else {
                fbuddy->status_rel_time = NULL;
            }

            /* if the buddy status has changed, update the contact list */
            if (fbuddy->status == NULL || !g_str_equal(fbuddy->status, status_text))
            {
                tmp = fbuddy->status;
                fbuddy->status = status_text;
                g_free(tmp);
                if (current_buddy_online)
                    purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
            } else {
                g_free(status_text);
            }
        } else {
            if (fbuddy->status != NULL)
            {
                g_free(fbuddy->status);
                fbuddy->status = NULL;
                if (current_buddy_online)
                {
                    /* update the status in the contact list */
                    purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
                }
            }
        }

        /* Set the buddy icon (if it hasn't changed) */
        search_tmp = strstr(search_start, "\"thumbSrc\":") + 12;
        if (search_tmp > largest_buddy_search_point)
            largest_buddy_search_point = search_tmp;
        buddy_icon_url = g_strndup(search_tmp, strchr(search_tmp, '"')-search_tmp);
        if (fbuddy->thumb_url == NULL || !g_str_equal(fbuddy->thumb_url, buddy_icon_url))
        {
            g_free(fbuddy->thumb_url);
            fbuddy->thumb_url = g_strdup(buddy_icon_url);

            /* Save the buddy icon so that they don't all need to be reloaded at startup */
            tmp = g_strdup_printf("buddy_icon_%d_cache", fbuddy->uid);
            purple_account_set_string(fba->account, tmp, buddy_icon_url);
            g_free(tmp);

            /* Turn the \/ into / */
            tmp = g_strcompress(buddy_icon_url);

            /* small icon at http://profile.ak.facebook.com/profile6/1845/74/q800753867_2878.jpg */
            /* bigger icon at http://profile.ak.facebook.com/profile6/1845/74/n800753867_2878.jpg */
            search_tmp = strstr(tmp, "/q");
            if (search_tmp)
                *(search_tmp + 1) = 'n';

            if (g_str_equal(tmp, "http://static.ak.fbcdn.net/pics/q_silhouette.gif"))
                /* User has no icon */
                purple_buddy_icons_set_for_user(fba->account,
                                                purple_buddy_get_name(buddy), NULL, 0, NULL);
            else
                /* Fetch their icon */
                fb_post_or_get(fba, FB_METHOD_GET, "profile.ak.facebook.com",
                               tmp + strlen("http://profile.ak.facebook.com"), NULL,
                               buddy_icon_cb, g_strdup(purple_buddy_get_name(buddy)),
                               FALSE);
            g_free(tmp);
        }
        g_free(buddy_icon_url);

        if (current_buddy_online)
        {
            /* Add buddy to the list of online buddies */
            online_buddies_list = g_slist_append(online_buddies_list, buddy);

            /* Update the display of the buddy in the buddy list and make the user online */
            if (!PURPLE_BUDDY_IS_ONLINE(buddy))
                purple_prpl_got_user_status(fba->account, buddy->name, purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE), NULL);
        }

        /* Move pointer after any user configurable data */
        search_start = search_tmp;
        /* Move pointer to the end of the buddy entry */
        search_start = strchr(largest_buddy_search_point, '}') + 1;
        while (*search_start == ',' && (search_start - data < data_len))
            search_start++;
    }

    buddies_list = purple_find_buddies(fba->account, NULL);
    if (buddies_list != NULL)
    {
        g_slist_foreach(buddies_list, (GFunc)set_buddies_offline, online_buddies_list);
        g_slist_free(buddies_list);
    }
    g_slist_free(online_buddies_list);
}