static void fb_auth_reject_cb(gpointer data)
{
	FacebookBuddy *fbuddy = data;
	FacebookAccount *fba = fbuddy->fba;
	gchar *buddy_uid;
	gchar *postdata;

	g_return_if_fail(fba != NULL);
	g_return_if_fail(fba->post_form_id != NULL);
	g_return_if_fail(fbuddy->uid != 0);

	buddy_uid = g_strdup_printf("%" G_GINT64_FORMAT, fbuddy->uid);

	postdata = g_strdup_printf(
			"type=friend_connect&id=%s&action=reject&"
			"post_form_id=%s&fb_dtsg=%s&"
			"post_form_id_source=AsyncRequest&__a=1",
			buddy_uid, fba->post_form_id, fba->dtsg);
	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/reqs.php",
			postdata, NULL, NULL, FALSE);

	g_hash_table_remove(fba->auth_buddies, buddy_uid);
	
	g_free(postdata);
	g_free(fbuddy);
	g_free(buddy_uid);
}
Example #2
0
void fb_blist_poke_buddy(PurpleBlistNode *node, gpointer data)
{
    PurpleBuddy *buddy;
    FacebookBuddy *fbuddy;
    FacebookAccount *fba;
    gchar *postdata;

    if(!PURPLE_BLIST_NODE_IS_BUDDY(node))
        return;
    buddy = (PurpleBuddy *) node;
    if (!buddy)
        return;
    fbuddy = buddy->proto_data;
    if (!fbuddy)
        return;
    fba = fbuddy->fba;
    if (!fba)
        return;

    postdata = g_strdup_printf("uid=%d&pokeback=0&post_form_id=%s", fbuddy->uid, fba->post_form_id);

    fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/poke.php",
                   postdata, NULL, NULL, FALSE);

    g_free(postdata);
}
void fb_buddy_delete(PurpleConnection *pc, PurpleBuddy *buddy,
		PurpleGroup *group)
{
	FacebookAccount *fba = pc->proto_data;
	gchar *buddy_tmp, *postdata;

	//This function removes a buddy from our friends list on facebook
	//and shouldn't really be used
	if (!purple_account_get_bool(fba->account, "facebook_manage_friends", FALSE)) {
		purple_debug_warning("facebook", "attempted to add %s but was blocked\n", buddy->name);
		return;
	}

	buddy_tmp = g_strdup(purple_url_encode(buddy->name));
	postdata = g_strdup_printf(
			"uid=%s&post_form_id=%s&fb_dtsg=%s&"
			"post_form_id_source=AsyncRequest&__a=1",
			buddy_tmp, fba->post_form_id, fba->dtsg);
	g_free(buddy_tmp);

	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/profile/removefriend.php",
			postdata, NULL, NULL, FALSE);

	g_free(postdata);
}
Example #4
0
static void fb_login(PurpleAccount *account)
{
	FacebookAccount *fba;
	gchar *postdata, *encoded_username, *encoded_password, *encoded_charset_test;
	const gchar* const *languages;
	const gchar *locale;
	
	/* Create account and initialize state */
	fba = g_new0(FacebookAccount, 1);
	fba->account = account;
	fba->pc = purple_account_get_connection(account);
	fba->uid = -1;
	fba->last_messages_download_time = time(NULL) - 60; /* 60 secs is a safe buffer */
	fba->cookie_table = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, g_free);
	fba->hostname_ip_cache = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, g_free);
	fba->sent_messages_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, NULL);
	fba->auth_buddies = g_hash_table_new_full(g_str_hash, g_str_equal,
			g_free, NULL);

	g_hash_table_replace(fba->cookie_table, g_strdup("test_cookie"),
			g_strdup("1"));

	account->gc->proto_data = fba;

	/* Error localized in libpurple jabber.c */
	if (!purple_ssl_is_supported()) {
		purple_connection_error_reason (purple_account_get_connection(account),
				PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
				_("Server requires TLS/SSL for login.  No TLS/SSL support found."));
		return;
	}

	purple_connection_set_state(fba->pc, PURPLE_CONNECTING);
	purple_connection_update_progress(fba->pc, _("Connecting"), 1, 3);

	encoded_username = g_strdup(purple_url_encode(
			purple_account_get_username(fba->account)));
	encoded_password = g_strdup(purple_url_encode(
			purple_account_get_password(fba->account)));
	encoded_charset_test = g_strdup(purple_url_encode("€,´,€,´,水,Д,Є"));
	languages = g_get_language_names();
	locale = languages[0];
	if (locale == NULL || g_str_equal(locale, "C"))
		locale = "en_US";

	g_hash_table_replace(fba->cookie_table, g_strdup("lsd"), g_strdup("abcde"));
	postdata = g_strdup_printf(
			"charset_test=%s&locale=%s&email=%s&pass=%s&pass_placeHolder=Password&persistent=1&login=Login&charset_test=%s&lsd=abcde",
			encoded_charset_test, locale, encoded_username, encoded_password, encoded_charset_test);
	g_free(encoded_username);
	g_free(encoded_password);
	g_free(encoded_charset_test);

	fb_post_or_get(fba, FB_METHOD_POST | FB_METHOD_SSL, "login.facebook.com",
			"/login.php?login_attempt=1&_fb_noscript=1", postdata, fb_login_cb, NULL, FALSE);
	g_free(postdata);
}
Example #5
0
static unsigned int fb_send_typing(PurpleConnection *pc, const gchar *name,
		PurpleTypingState state)
{
	int typing_state;
	gchar *postdata;
	FacebookAccount *fba = pc->proto_data;
	gchar *encoded_name;

	g_return_val_if_fail(fba != NULL, 0);
	g_return_val_if_fail(fba->post_form_id != NULL, 0);

	typing_state = (state == PURPLE_TYPING) ? 1 : 0;

	/* Don't send typing notifications to self */
	if (atoll(name) != fba->uid)
	{
		encoded_name = g_strdup(purple_url_encode(name));
		postdata = g_strdup_printf("typ=%d&to=%s&post_form_id=%s",
				typing_state, encoded_name, fba->post_form_id);
		g_free(encoded_name);
		fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/chat/typ.php",
				postdata, NULL, NULL, FALSE);
		g_free(postdata);
	} else {
		serv_got_typing(pc, name, 10, state);
	}

	/* 7 is the number of seconds before sending the new typing state.  It
	 * corresponds with the default value that Facebook waits. */
	return 7;
}
Example #6
0
gboolean fb_reconnect(FacebookAccount *fba)
{
	gchar *url = g_strdup_printf("/ajax/presence/reconnect.php?__a=1&reason=7&post_form_id=%s&__a=1", fba->post_form_id);
	fb_post_or_get(fba, FB_METHOD_GET, NULL, url, NULL, got_reconnect_json, NULL, FALSE);
	g_free(url);
	
	return FALSE;
}
Example #7
0
void fb_login_captcha_ok_cb(PurpleConnection *pc, PurpleRequestFields *fields)
{
	const gchar *captcha_response;
	gchar *postdata, *encoded_username, *encoded_password, *encoded_charset_test,
			*encoded_persist_data, *encoded_response, *encoded_extra_challenge,
			*encoded_session;
	FacebookAccount *fba = pc->proto_data;

	captcha_response = purple_request_fields_get_string(fields, "captcha_response");
	
	encoded_response = g_strdup(purple_url_encode(captcha_response));
	encoded_username = g_strdup(purple_url_encode(
			purple_account_get_username(fba->account)));
	encoded_password = g_strdup(purple_url_encode(
			purple_account_get_password(fba->account)));
	encoded_extra_challenge = g_strdup(purple_url_encode(
			fba->extra_challenge));
	encoded_persist_data = g_strdup(purple_url_encode(
			fba->persist_data));
	encoded_session = g_strdup(purple_url_encode(
			fba->captcha_session));
	encoded_charset_test = g_strdup(purple_url_encode("€,´,€,´,水,Д,Є"));

	postdata = g_strdup_printf("charset_test=%s&"
								"version=1.0&"
								"return_session=0&"
								"charset_test=%s&"
								"answered_captcha=1&"
								"captcha_persist_data=%s&"
								"captcha_session=%s&"
								"extra_challenge_params=%s&"
								"captcha_response=%s&"
								"email=%s&pass=%s&"
								"persistent=1",
								encoded_charset_test, encoded_charset_test,
								encoded_persist_data, encoded_session,
								encoded_extra_challenge, encoded_response,
								encoded_username, encoded_password);
	g_free(encoded_username);
	g_free(encoded_password);
	g_free(encoded_charset_test);
	g_free(encoded_extra_challenge);
	g_free(encoded_persist_data);
	g_free(encoded_response);
	g_free(encoded_session);

	fb_post_or_get(fba, FB_METHOD_POST | FB_METHOD_SSL, "login.facebook.com",
			"/login.php?login_attempt=1&_fb_noscript=1", postdata, fb_login_cb, NULL, FALSE);
	g_free(postdata);
	
	g_free(fba->extra_challenge);
	g_free(fba->persist_data);
	g_free(fba->captcha_session);
	fba->extra_challenge = NULL;
	fba->persist_data = NULL;
	fba->captcha_session = NULL;
}
Example #8
0
gboolean fb_check_friend_requests(gpointer data)
{
	FacebookAccount *fba;

	fba = data;

	if (purple_account_get_bool(
			fba->account, "facebook_manage_friends", FALSE)) {
		fb_post_or_get(fba, FB_METHOD_GET, NULL, "/reqs.php", NULL,
				fb_check_friend_request_cb, NULL, FALSE);
	}

	return TRUE;
}
Example #9
0
gboolean fb_get_buddy_list(gpointer data)
{
    FacebookAccount *fba;
    gchar *postdata;

    fba = data;

    postdata = g_strdup_printf(
                   "user=%d&popped_out=false&force_render=true&buddy_list=1",
                   fba->uid);
    fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/presence/update.php",
                   postdata, got_buddy_list_cb, NULL, FALSE);
    g_free(postdata);

    return TRUE;
}
Example #10
0
static void handle_move_request(FacebookAccount *fba, MoveRequest *request)
{
	const gchar *old_list_id;
	const gchar *new_list_id;
	gchar *postdata;
	gboolean remove_flist, no_original_list;
	const gchar *command;

	purple_debug_info("facebook",
		"handling movement of %s from %s to %s\n",
		request->who, request->old_group, request->new_group);

	old_list_id = fb_get_list_id(fba, request->old_group);
	new_list_id = fb_get_list_id(fba, request->new_group);

	remove_flist = !new_list_id || g_str_equal(new_list_id, "-1");
	no_original_list = !old_list_id || g_str_equal(old_list_id, "-1");

	if (remove_flist) {
		command = "&remove_fl=true";
	} else if (no_original_list) {
		command = "&add_fl=true";
	} else {
		command = "&move_fl=true";
	}

	postdata = g_strdup_printf(
		"post_form_id=%s&drag_uid=%s&user=%" G_GINT64_FORMAT
		"&new_flid=%s&old_flid=%s%s",
		fba->post_form_id,
		request->who,
		fba->uid,
		remove_flist ? "" : new_list_id,
		no_original_list ? "" : old_list_id,
		command);

	fb_post_or_get(fba, FB_METHOD_POST, NULL,
		"/ajax/chat/buddy_list_settings.php",
		postdata, NULL, NULL, FALSE);

	g_free(postdata);

	g_free(request->who);
	g_free(request->old_group);
	g_free(request->new_group);
	g_free(request);
}
Example #11
0
/* This code should never be reinstated in it's current form.  Period.  See
 * issue 185 for why */
static void fb_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
{
	gchar *postdata;
	FacebookAccount *fba = pc->proto_data;

	if (atoi(buddy->name) == fba->uid)
	{
		purple_account_set_bool(fba->account, "facebook_hide_self", TRUE);
		return;
	}

	postdata = g_strdup_printf("uid=%s&post_form_id=%s", buddy->name, fba->post_form_id);

	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/removefriend.php", postdata, NULL, NULL, FALSE);

	g_free(postdata);
}
Example #12
0
/* Message fetch loop.  An invariant here is that get_new_messages()
 * is the only function which can create a new timer for
 * new_messages_check_timer.  The timer always calls got_new_messages(),
 * and got_new_messages always calls get_new_messages (either directly
 * or indirectly).  To start the loops off, get_new_messages should be
 * called ONCE and only ONCE.  After that the timers will take care of
 * themselves until final cleanup.
 */
gboolean fb_get_new_messages(FacebookAccount *fba)
{
	time_t now;
	gchar *fetch_url;
	gchar *fetch_server;
	const gchar *channel_number;

	fba->new_messages_check_timer = 0;

	now = time(NULL);
	if (fba->last_messages_download_time > now - 3) {
		/*
		 * Wait a bit before fetching more messages, to make sure we
		 * never hammer their servers.
		 *
		 * TODO: This could be smarter.  Like, allow 3 requests per
		 *       10 seconds or something.
		 */
		fba->new_messages_check_timer = purple_timeout_add_seconds(
				3 - (now - fba->last_messages_download_time),
				(GSourceFunc)fb_get_new_messages, fba);
		return FALSE;
	}

	if (fba->channel_number == NULL)
	{
		return FALSE;
	} else {
		channel_number = fba->channel_number;
	}

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

	fetch_server = g_strdup_printf("%d.%s.facebook.com", 0, channel_number);
	/* use the current time in the url to get past any transparent proxy caches */
	fetch_url = g_strdup_printf("/x/%lu/%s/p_%" G_GINT64_FORMAT "=%d", (gulong)time(NULL), (fba->is_idle?"false":"true"), fba->uid, fba->message_fetch_sequence);

	fb_post_or_get(fba, FB_METHOD_GET, fetch_server, fetch_url, NULL, got_new_messages, fba->pc, TRUE);
	fba->last_messages_download_time = now;

	g_free(fetch_url);
	g_free(fetch_server);

	return FALSE;
}
Example #13
0
gboolean fb_get_notifications_feed(FacebookAccount *fba)
{
	const gchar *feed_url;

	if (purple_account_get_bool(fba->account, "facebook_get_notifications", TRUE)) {
		feed_url = purple_account_get_string(fba->account, "notifications_feed_url", NULL);
		if (!feed_url)
		{
			purple_debug_info("facebook", "no notifications feed url available, searching for it\n");
			fb_find_feed_url(fba);
			return TRUE;
		}

		fb_post_or_get(fba, FB_METHOD_GET, NULL, feed_url, NULL, fb_got_notifications_cb, NULL, FALSE);
	}

	return TRUE;
}
Example #14
0
static void fb_login_captcha_cb(FacebookAccount *fba, gchar *response, 
		gsize len, gpointer userdata)
{
	const gchar *challenge_start = "challenge : '";
	gchar *challenge;
	gchar *image_url;
	
	challenge = g_strstr_len(response, len, challenge_start);
	if (challenge)
	{
		challenge += strlen(challenge_start);
		challenge = g_strndup(challenge, strchr(challenge, '\'') - challenge);
		
		image_url = g_strdup_printf("/image?c=%s", challenge);
		
		fb_post_or_get(fba, FB_METHOD_GET | FB_METHOD_SSL, "api-secure.recaptcha.net",
			image_url, NULL, fb_login_captcha_image_cb, NULL, FALSE);
	}
}
Example #15
0
static gboolean fb_send_im_fom(FacebookOutgoingMessage *msg)
{
	gchar *encoded_message;
	gchar *postdata;
	gchar *jstime;
	
	jstime = g_strdup_printf("%ld%ld", msg->time.tv_sec, (msg->time.tv_usec/1000));

	encoded_message = g_strdup(purple_url_encode(msg->message));
		postdata = g_strdup_printf("msg_text=%s&msg_id=%d&to=%s&client_time=%s&post_form_id=%s&fb_dtsg=%s",
			encoded_message, msg->msg_id, msg->who, jstime,
			msg->fba->post_form_id ? msg->fba->post_form_id : "0",msg->fba->dtsg?msg->fba->dtsg:"(null)");
	g_free(encoded_message);
	g_free(jstime);

	fb_post_or_get(msg->fba, FB_METHOD_POST, NULL, "/ajax/chat/send.php?__a=1", postdata, fb_send_im_cb, msg, FALSE);
	g_free(postdata);

	return FALSE;
}
Example #16
0
PurpleConversation *
fb_find_chat(FacebookAccount *fba, const gchar *group)
{
	PurpleConversation *conv;
	gchar *postdata;
	
	conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, group, fba->account);
	
	if (conv == NULL)
	{
		conv = serv_got_joined_chat(fba->pc, atoi(group), group);
		
		postdata = g_strdup_printf("gid=%s&post_form_id=%s&fb_dtsg=%s&lsd=", group,
					fba->post_form_id, fba->dtsg);
		fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/groups/chat/update_facepiles.php?__a=1",
			postdata, fb_got_facepile, g_strdup(group), FALSE);
		g_free(postdata);
	}
	
	return conv;
}
Example #17
0
static void fb_auth_reject_cb(gpointer data)
{
	FacebookBuddy *fbuddy = data;
	FacebookAccount *fba = fbuddy->fba;
	gchar *postdata;

	g_return_if_fail(fba != NULL);
	g_return_if_fail(fba->post_form_id != NULL);
	g_return_if_fail(fbuddy->uid != 0);

	postdata = g_strdup_printf(
			"type=friend_add&id=%d&action=reject&post_form_id=%s",
			fbuddy->uid, fba->post_form_id);
	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/reqs.php",
			postdata, NULL, NULL, FALSE);
	g_free(postdata);

	fba->auth_buddies = g_slist_remove(fba->auth_buddies,
			GINT_TO_POINTER(fbuddy->uid));

	g_free(fbuddy);
}
void fb_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
{
	gchar *postdata;
	FacebookAccount *fba = pc->proto_data;
	gchar *buddy_tmp;

	if (!purple_account_get_bool(
				fba->account, "facebook_manage_friends", FALSE)) {
		/*
		 * We used to pop up dialogs here but if a user renamed a group,
		 * this would spawn message for each person in the buddy list.  Bad!
		purple_notify_info(fba->pc, _("Friend not added"),
				_("Adding Facebook friends via Pidgin is disabled"),
				_("Either add a friend via Facebook.com or edit your account preferences"));
		*/
		purple_debug_warning("facebook", "attempted to add %s but was blocked\n", buddy->name);
		return;
	}

	if (atoll(buddy->name) == fba->uid)
	{
		purple_account_set_bool(fba->account,
				"facebook_hide_self", FALSE);
		return;
	}

	buddy_tmp = g_strdup(purple_url_encode(buddy->name));
	postdata = g_strdup_printf(
			"user=%" G_GINT64_FORMAT "&profile_id=%s&message=&"
			"source=&submit=1&post_form_id=%s&fb_dtsg=%s&"
			"post_form_id_source=AsyncRequest&__a=1",
			fba->uid, buddy_tmp, fba->post_form_id, fba->dtsg);
	g_free(buddy_tmp);

	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/profile/connect.php",
			postdata, NULL, NULL, FALSE);

	g_free(postdata);
}
Example #19
0
static void fb_set_status_ok_cb(gpointer data, const gchar *status_text)
{
	PurpleConnection *pc = data;
	FacebookAccount *fba = pc->proto_data;
	gchar *postdata;
	gchar *status_tmp;
	gchar *status_text_new;

	g_return_if_fail(fba->post_form_id != NULL);

	status_text_new = g_strstrip(g_strdup(status_text));

	/* don't set the status if it's idential to what we've already set */
	if (fba->last_status_message && g_str_equal(fba->last_status_message,
				status_text_new)) {
		g_free(status_text_new);
		return;
	}

	g_free(fba->last_status_message);
	fba->last_status_message = status_text_new;

	if (*status_text_new != '\0')
	{
		status_tmp = g_strdup(purple_url_encode(status_text_new));
		postdata = g_strdup_printf("profile_id=%" G_GINT64_FORMAT "&status=%s&post_form_id=%s",
				fba->uid, status_tmp, fba->post_form_id);
		g_free(status_tmp);
	}
	else
		postdata = g_strdup_printf("profile_id=%" G_GINT64_FORMAT "&clear=1&post_form_id=%s",
				fba->uid, fba->post_form_id);

	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/updatestatus.php",
			postdata, NULL, NULL, FALSE);

	g_free(postdata);
}
Example #20
0
static void create_friend_list(FacebookAccount *fba, const gchar *new_group,
	MoveRequest *request)
{
	gchar *postdata;
	gchar *new_group_escaped;

	purple_debug_info("facebook", "creating friend list %s\n", new_group);

	new_group_escaped = fb_strdup_withhtml(new_group);

	postdata = g_strdup_printf(
		"post_form_id=%s&create=%s&user=%" G_GINT64_FORMAT,
		fba->post_form_id,
		new_group_escaped,
		fba->uid);

	fb_post_or_get(fba, FB_METHOD_POST, NULL,
		"/ajax/chat/buddy_list_settings.php",
		postdata, create_list_cb, request, FALSE);

	g_free(postdata);
	g_free(new_group_escaped);
}
Example #21
0
void fb_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
{
	gchar *postdata;
	gchar *url;
	FacebookAccount *fba = pc->proto_data;
	gchar *buddy_tmp;

	if (!purple_account_get_bool(
				fba->account, "facebook_manage_friends", FALSE)) {
		purple_notify_info(fba->pc, _("Friend not added"),
				_("Adding Facebook friends via Pidgin is disabled"),
				_("Either add a friend via Facebook.com or edit your account preferences"));
		// TODO: Message here
		return;
	}

	if (atoi(buddy->name) == fba->uid)
	{
		purple_account_set_bool(fba->account,
				"facebook_hide_self", FALSE);
		return;
	}

	buddy_tmp = g_strdup(purple_url_encode(buddy->name));
	postdata = g_strdup_printf(
			"confirmed=1&add=Add+Friend&action=follow_up&uid=%s&flids=&flid_name=&source=search&is_from_whitelist=0&message=&failed_captcha=0&post_form_id=%s",
			buddy_tmp, fba->post_form_id);
	url = g_strdup_printf("/ajax/addfriend.php?id=%s", buddy_tmp);
	g_free(buddy_tmp);

	fb_post_or_get(fba, FB_METHOD_POST, NULL, url, postdata,
			NULL, NULL, FALSE);

	g_free(postdata);
	g_free(url);
}
Example #22
0
static void fb_login_cb(FacebookAccount *fba, gchar *response, gsize len,
		gpointer userdata)
{
	gchar *user_cookie;
	const gchar *persist_data_start;
	gchar *persist_data;
	const gchar *session_start;
	gchar *session;
	gchar *captcha_url;
	const gchar *extra_challenge_params;
	gchar *extra_challenge;
	if (len && g_strstr_len(response, len, "captcha"))
	{
		purple_debug_info("facebook", "captcha page: %s\n", response);

		purple_connection_update_progress(fba->pc, _("Handling Captcha"), 2, 4);
		
		persist_data_start = "<input type=\"hidden\" id=\"captcha_persist_data\" name=\"captcha_persist_data\" value=\"";
		persist_data = g_strstr_len(response, len, persist_data_start);
		if (persist_data)
		{
			persist_data += strlen(persist_data_start);
			fba->persist_data = g_strndup(persist_data, strchr(persist_data, '"') - persist_data);
		}
		
		session_start = "<input type=\"hidden\" id=\"captcha_session\" name=\"captcha_session\" value=\"";
		session = g_strstr_len(response, len, session_start);
		if (session)
		{
			session += strlen(session_start);
			fba->captcha_session = g_strndup(session, strchr(session, '"') - session);
		}
		
		
		extra_challenge_params = "<input type=\"hidden\" id=\"extra_challenge_params\" name=\"extra_challenge_params\" value=\"";
		extra_challenge = g_strstr_len(response, len, extra_challenge_params);
		if (extra_challenge)
		{
			extra_challenge += strlen(extra_challenge_params);
			fba->extra_challenge = g_strndup(extra_challenge, strchr(extra_challenge, '"') - extra_challenge);
			extra_challenge = purple_unescape_html(fba->extra_challenge);
			g_free(fba->extra_challenge);
			fba->extra_challenge = extra_challenge;
		}
		
		if (!fba->extra_challenge || !fba->persist_data || !fba->captcha_session)
		{
			purple_debug_info("facebook", "captcha response: %s\n", response);
			g_free(fba->extra_challenge);
			g_free(fba->persist_data);
			g_free(fba->captcha_session);
			fba->extra_challenge = NULL;
			fba->persist_data = NULL;
			fba->captcha_session = NULL;
			purple_connection_error_reason(fba->pc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
				"Could not authenticate captcha.  Logging into the Facebook website may fix this.");
			return;
		}
		
		captcha_url = g_strdup_printf("/challenge?k=" FACEBOOK_CAPTCHA_SITE "&%s",
				fba->extra_challenge?fba->extra_challenge:"");
		
		fb_post_or_get(fba, FB_METHOD_GET | FB_METHOD_SSL, "api-secure.recaptcha.net",
			captcha_url, NULL, fb_login_captcha_cb, NULL, FALSE);
		
		g_free(captcha_url);
		
		return;
	}

	purple_connection_update_progress(fba->pc, _("Authenticating"), 2, 3);

	/* Look for our uid */
	user_cookie = g_hash_table_lookup(fba->cookie_table, "c_user");
	if (user_cookie == NULL) {
		/*
		 * Server didn't set the c_user cookie, so we must have given
		 * them a bad username or password
		 */
		purple_connection_error_reason(fba->pc,
				PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
				_("Incorrect username or password."));
		return;
	}
	fba->uid = atoll(user_cookie);
	purple_debug_info("facebook", "uid %" G_GINT64_FORMAT "\n", fba->uid);

	/* ok, we're logged in now! */
	purple_connection_set_state(fba->pc, PURPLE_CONNECTED);

	/* This will kick off our long-poll message retrieval loop */
	fb_get_post_form_id(fba);
	fb_check_friend_requests(fba);

	/* periodically check for people adding you to their facebook friend list */
	fba->friend_request_timer = purple_timeout_add_seconds(60 * 5,
			fb_check_friend_requests, fba);

	/* periodically check for new notifications */
	fba->notifications_timer = purple_timeout_add_seconds(60,
			(GSourceFunc)fb_get_notifications_feed, fba);

	/* Periodically check for new messages.  NOTE: This MUST exist,
	 * regardless of other other mechanisms for checking messages.  This
	 * is because the code needs a failsafe checker in case other one of
	 * the other retrieval mechanisms dies due to a bad request, etc.
	 * Without such a failsafe, a user will receive no messages, which is
	 * one of hardest bugs to debug and get reports about.  Hence, the
	 * importance of this loop.
	 * That said, there is room for tweaking this loop and possibly even
	 * setting it such that it is the primary or only message checker.
	 * The key is that the method must NEVER die until logout.
	 */
	fba->perpetual_messages_timer = purple_timeout_add_seconds(15,
			(GSourceFunc)fb_get_messages_failsafe, fba);

	/* init blist subsystem */
	fb_blist_init(fba);

	/* init conversation subsystem */
	fb_conversation_init(fba);
}
Example #23
0
void
fb_get_groups(FacebookAccount *fba)
{
	fb_post_or_get(fba, FB_METHOD_GET, NULL, "/ajax/home/groups.php?__a=1", NULL, fb_got_groups, NULL, FALSE);
}
Example #24
0
gboolean fb_get_post_form_id(FacebookAccount *fba, FacebookFunc callback)
{
	fb_post_or_get(fba, FB_METHOD_GET, NULL, "/presence/popout.php", NULL, got_form_id_page, callback, FALSE);
	return FALSE;
}
Example #25
0
static void fb_find_feed_url(FacebookAccount *fba)
{
	fb_post_or_get(fba, FB_METHOD_GET, NULL, "/notifications.php", NULL,
			find_feed_url_cb, NULL, FALSE);
}
Example #26
0
static void fb_close(PurpleConnection *pc)
{
	FacebookAccount *fba;
	gchar *postdata;
	GSList *buddies;

	purple_debug_info("facebook", "disconnecting account\n");

	g_return_if_fail(pc != NULL);
	g_return_if_fail(pc->proto_data != NULL);
	
	fba = pc->proto_data;

	if ( fba == NULL )		//VOXOX - JRT - 2009.10.12 - Prevent crash when network is lost or resuming from hibernation.
		return;

	purple_debug_info("facebook", "unloading plugin\n");

	/* destroy blist subsystem */
	fb_blist_destroy(fba);

	/* destroy conversation subsystem */
	fb_conversation_destroy(fba);
	buddies = purple_find_buddies(fba->account, NULL);
	while(buddies) {
		PurpleBuddy *b = buddies->data;
		fb_buddy_free(b);
		buddies = g_slist_delete_link(buddies, buddies);
	}

	/* Tell Facebook that we've logged out. */
	/*
	 * TODO
	 * This doesn't actually work because the request is non-blocking
	 * and we're in the process of logging out.  So we start making a
	 * connection but then libpurple immediately cancels the attempt
	 * and frees everything.
	 *
	 * There are two ways to fix this:
	 * 1. We could make this request, but not pass in fba or reference
	 *    any other data.  The request could complete normally even
	 *    after this account has logged out, since it really doesn't
	 *    need access to the PurpleConnection or the FacebookAccount.
	 *
	 * 2. The close prpl callback could be changed in libpurple so that
	 *    protocol plugins can have a chance to make network requests
	 *    and do other long cleanup operations.  So the call to
	 *    prpl->close() would become asynchronous.  It tells the
	 *    protocol plugin to begin the shutdown sequence, and the
	 *    protocol plugin tells the core when it's finished.
	 */
	if (fba->post_form_id)
		postdata = g_strdup_printf(
				"visibility=false&post_form_id=%s&"
				"fb_dtsg=%s&post_form_id_source=AsyncRequest&"
				"__a=1",
				fba->post_form_id, fba->dtsg);
	else
		postdata = g_strdup("visibility=false");
	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/chat/settings.php",
			postdata, NULL, NULL, FALSE);
	g_free(postdata);

	if (fba->friend_request_timer) {
		purple_timeout_remove(fba->friend_request_timer);
	}
	if (fba->notifications_timer) {
		purple_timeout_remove(fba->notifications_timer);
	}
	if (fba->new_messages_check_timer) {
		purple_timeout_remove(fba->new_messages_check_timer);
	}
	if (fba->perpetual_messages_timer) {
		purple_timeout_remove(fba->perpetual_messages_timer);
	}

	purple_debug_info("facebook", "destroying %d incomplete connections\n",
			g_slist_length(fba->conns));

	while (fba->conns != NULL)
		fb_connection_destroy(fba->conns->data);

	while (fba->dns_queries != NULL) {
		PurpleDnsQueryData *dns_query = fba->dns_queries->data;
		purple_debug_info("facebook", "canceling dns query for %s\n",
					purple_dnsquery_get_host(dns_query));
		fba->dns_queries = g_slist_remove(fba->dns_queries, dns_query);
		purple_dnsquery_destroy(dns_query);
	}
	
	if (fba->resending_messages != NULL) {
		fb_cancel_resending_messages(fba);
	}

	//VOXOX - JRT - 2009.10.13 - I know we are deleting fba anyway, but since other threads may also be accessing this,
	//							 it helps reduce crashes due to freed memory ptrs.  (There is no thread syncing to control this better).
	g_hash_table_destroy(fba->cookie_table);

	g_hash_table_destroy(fba->hostname_ip_cache);

	g_hash_table_destroy(fba->auth_buddies);

	g_free(fba->post_form_id);
	g_free(fba->dtsg);
	g_free(fba->channel_number);
	g_free(fba->last_status_message);
	g_free(fba->extra_challenge);
	g_free(fba->captcha_session);
	g_free(fba->persist_data);
	g_free(fba);

}
Example #27
0
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);
}