Example #1
0
static sd_dhcp_client *client_stop(sd_dhcp_client *client, int error) {
        assert_return(client, NULL);

        if (error < 0)
                log_dhcp_client(client, "STOPPED: %s", strerror(-error));
        else {
                switch(error) {
                case DHCP_EVENT_STOP:
                        log_dhcp_client(client, "STOPPED");
                        break;
                case DHCP_EVENT_NO_LEASE:
                        log_dhcp_client(client, "STOPPED: No lease");
                        break;
                default:
                        log_dhcp_client(client, "STOPPED: Unknown reason");
                        break;
                }
        }

        client = client_notify(client, error);

        if (client)
                client_initialize(client);

        return client;
}
static int client_stop(sd_dhcp_client *client, int error) {
        assert_return(client, -EINVAL);

        client->receive_message =
                sd_event_source_unref(client->receive_message);

        if (client->fd >= 0)
                close_nointr_nofail(client->fd);
        client->fd = -1;

        client->timeout_resend = sd_event_source_unref(client->timeout_resend);

        client->timeout_t1 = sd_event_source_unref(client->timeout_t1);
        client->timeout_t2 = sd_event_source_unref(client->timeout_t2);
        client->timeout_expire = sd_event_source_unref(client->timeout_expire);

        client->attempt = 1;

        client_notify(client, error);

        client->start_time = 0;
        client->secs = 0;
        client->state = DHCP_STATE_INIT;

        if (client->lease)
                client->lease = sd_dhcp_lease_unref(client->lease);

        log_dhcp_client(client, "STOPPED");

        return 0;
}
Example #3
0
static sd_dhcp_client *client_stop(sd_dhcp_client *client, int error) {
        assert_return(client, NULL);

        log_dhcp_client(client, "STOPPED: %s", strerror(-error));

        client = client_notify(client, error);

        if (client)
                client_initialize(client);

        return client;
}
Example #4
0
static int client_timeout_expire(sd_event_source *s, uint64_t usec,
                                 void *userdata) {
        sd_dhcp_client *client = userdata;

        log_dhcp_client(client, "EXPIRED");

        client = client_notify(client, DHCP_EVENT_EXPIRED);

        /* lease was lost, start over if not freed or stopped in callback */
        if (client && client->state != DHCP_STATE_STOPPED) {
                client_initialize(client);
                client_start(client);
        }

        return 0;
}
Example #5
0
bool facebook_client::home( )
{
	handle_entry( "home" );

	http::response resp = flap( FACEBOOK_REQUEST_HOME );

	// Process result data
	validate_response(&resp);

	switch ( resp.code )
	{
	case HTTP_CODE_OK:
	{		
		if ( resp.data.find( "id=\"navAccountName\"" ) != std::string::npos )
		{ // Backup for old fb version
			// Get real_name
			this->self_.real_name = utils::text::remove_html( utils::text::special_expressions_decode( utils::text::source_get_value( &resp.data, 2, " id=\"navAccountName\">", "</a" ) ) );
			DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NAME,this->self_.real_name.c_str());
			DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NICK,this->self_.real_name.c_str());
			parent->Log("      Got self real name: %s", this->self_.real_name.c_str());
		} else if ( resp.data.find("id=\"pageNav\"") != std::string::npos ) {
			// Get real_name
			this->self_.real_name = utils::text::remove_html( utils::text::special_expressions_decode( utils::text::source_get_value( &resp.data, 3, " class=\"headerTinymanName\"", ">", "</a" ) ) );
			DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NAME,this->self_.real_name.c_str());
			DBWriteContactSettingUTF8String(NULL,parent->m_szModuleName,FACEBOOK_KEY_NICK,this->self_.real_name.c_str());
			parent->Log("      Got self real name: %s", this->self_.real_name.c_str());
		} else {
			client_notify(TranslateT("Something happened to Facebook. Maybe there was some major update so you should wait for an update."));
			return handle_error( "home", FORCE_DISCONNECT );
		}

		// Get avatar
		std::string avatar = utils::text::source_get_value( &resp.data, 3, "class=\\\"fbxWelcomeBoxImg", "src=\\\"", "\\\"" );
		if (avatar.empty())
			avatar = utils::text::source_get_value( &resp.data, 3, "class=\"fbxWelcomeBoxImg", "src=\"", "\"" );

		this->self_.image_url = utils::text::trim( utils::text::special_expressions_decode( avatar ) );
		parent->Log("      Got self avatar: %s", this->self_.image_url.c_str());
		parent->CheckAvatarChange(NULL, this->self_.image_url);

		// Get post_form_id
		this->post_form_id_ = utils::text::source_get_value( &resp.data, 3, "name=\"post_form_id\"", "value=\"", "\"" );
		parent->Log("      Got self post form id: %s", this->post_form_id_.c_str());

		// Get dtsg
		this->dtsg_ = utils::text::source_get_value( &resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"" );
		parent->Log("      Got self dtsg: %s", this->dtsg_.c_str());

		// Get logout hash
		this->logout_hash_ = utils::text::source_get_value( &resp.data, 2, "<input type=\"hidden\" autocomplete=\"off\" name=\"h\" value=\"", "\"" );
		parent->Log("      Got self logout hash: %s", this->logout_hash_.c_str());
			
		// TODO: DIrectly get that friend requests
		// Get friend requests count and notify it
		std::string str_count = utils::text::source_get_value( &resp.data, 2, "<span id=\"requestsCountValue\">", "</span>" );
		if ( str_count.length() && str_count != std::string( "0" ) )
		{
			std::string message = Translate("Got new friend requests: ") + str_count;

			TCHAR* tmessage = mir_a2t(message.c_str());
			parent->NotifyEvent( parent->m_tszUserName, tmessage, NULL, FACEBOOK_EVENT_OTHER, TEXT(FACEBOOK_URL_REQUESTS) );
			mir_free( tmessage );
		}

		if (!DBGetContactSettingByte(NULL,parent->m_szModuleName,FACEBOOK_KEY_PARSE_MESSAGES, DEFAULT_PARSE_MESSAGES))
		{
			str_count = utils::text::source_get_value( &resp.data, 2, "<span id=\"messagesCountValue\">", "</span>" );
			if ( str_count.length() && str_count != std::string( "0" ) )
			{
				std::string message = Translate("Got new messages: ") + str_count;

				TCHAR* tmessage = mir_a2t(message.c_str());
				parent->NotifyEvent( parent->m_tszUserName, tmessage, NULL, FACEBOOK_EVENT_OTHER, TEXT(FACEBOOK_URL_MESSAGES) );
				mir_free( tmessage );
			}
		}
			
		str_count = utils::text::source_get_value( &resp.data, 2, "<span id=\"notificationsCountValue\">", "</span>" );
		if ( str_count.length() && str_count != std::string( "0" ) )
		{
			// Parse notifications directly to popups
			ForkThread( &FacebookProto::ProcessNotifications, this->parent, NULL );
		}

		if (DBGetContactSettingByte(NULL, parent->m_szModuleName, FACEBOOK_KEY_ENABLE_GROUPCHATS, DEFAULT_ENABLE_GROUPCHATS)) {
			// Get group chats
			std::string favorites = utils::text::source_get_value( &resp.data, 2, "<div id=\"leftCol\"", "<div id=\"contentCol\"" );

			std::string::size_type pos = 0;
			while ((pos = favorites.find("href=\"/groups/",pos)) != std::string::npos) {
				pos += 14;
				std::string item = favorites.substr(pos, favorites.find("</a>", pos) - pos);
				std::string id = item.substr(0, item.find("/"));
		
				if (!id.empty()) {
					std::string name = utils::text::source_get_value( &item, 3, "class=\"linkWrap", ">", "</div>" );
					name = utils::text::special_expressions_decode(utils::text::slashu_to_utf8( name ) );
					parent->Log("      Got new group chat: %s (id: %s)", name.c_str(), id.c_str());
					if (!name.empty())
						parent->AddChat(id.c_str(), name.c_str());
				}
			}
		}

		return handle_success( "home" );

	}
	case HTTP_CODE_FOUND:
		// Work-around for replica_down, f**king hell what's that?
		parent->Log("      REPLICA_DOWN is back in force!");
		return this->home();
	
	default:
		return handle_error( "home", FORCE_DISCONNECT );
	}
}
Example #6
0
bool facebook_client::login(const std::string &username,const std::string &password)
{
	handle_entry( "login" );

	username_ = username;
	password_ = password;

	// Access homepage to get initial cookies
	flap( FACEBOOK_REQUEST_HOME, NULL );

	// Prepare login data
	std::string data = "charset_test=%e2%82%ac%2c%c2%b4%2c%e2%82%ac%2c%c2%b4%2c%e6%b0%b4%2c%d0%94%2c%d0%84&locale=en&email=";
	data += utils::url::encode( username );
	data += "&pass="******"&pass_placeHolder=Password&login=Login&persistent=1";

	// Send validation
	http::response resp = flap( FACEBOOK_REQUEST_LOGIN, &data );

	// Process result data
	validate_response(&resp);

	if ( resp.code == HTTP_CODE_FOUND && resp.headers.find("Location") != resp.headers.end() )
	{
		// Check whether some Facebook things are required
		if ( resp.headers["Location"].find("help.php") != std::string::npos )
		{
			client_notify( TranslateT("Login error: Some Facebook things are required.") );
			parent->Log(" ! !  Login error: Some Facebook things are required.");
			// return handle_error( "login", FORCE_DISCONNECT );
		}
		
		// Check whether setting Machine name is required
		if ( resp.headers["Location"].find("/checkpoint/") != std::string::npos )
		{
			resp = flap( FACEBOOK_REQUEST_SETUP_MACHINE );
			
			std::string inner_data = "machine_name=MirandaIM&submit[Save%20Device]=Save%20Device";
			inner_data += "&post_form_id=";
			inner_data += utils::text::source_get_value(&resp.data, 3, "name=\"post_form_id\"", "value=\"", "\"" );
			
			inner_data += "&lsd=";
			inner_data += utils::text::source_get_value(&resp.data, 3, "name=\"lsd\"", "value=\"", "\"" );
			
			inner_data += "&nh=";
			inner_data += utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"" );

			resp = flap( FACEBOOK_REQUEST_SETUP_MACHINE, &inner_data );
			validate_response(&resp);
		}
	}
	
	if ( resp.code == HTTP_CODE_FOUND && resp.headers.find("Location") != resp.headers.end() )
	{
		// Check whether HTTPS connection is required and we don't have enabled it
		if (!this->https_)
		{    
			if ( resp.headers["Location"].find("https://") != std::string::npos )
			{
				client_notify(TranslateT("Your account requires HTTPS connection. Activating."));
				DBWriteContactSettingByte(NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS, 1);
				this->https_ = true;
			}
		}

	}

	// Check for Device ID
	if ( cookies["datr"].length() )
		DBWriteContactSettingString( NULL, parent->m_szModuleName, FACEBOOK_KEY_DEVICE_ID, cookies["datr"].c_str() );

	switch ( resp.code )
	{
	case HTTP_CODE_FAKE_DISCONNECTED:
	{
		// When is error only because timeout, try login once more
		if ( handle_error( "login" ) )
			return login(username, password);
		else
			return false;
	}

	case HTTP_CODE_OK: // OK page returned, but that is regular login page we don't want in fact
	{ 
		// Check whether captcha code is required
		if ( resp.data.find("id=\"captcha\"") != std::string::npos )
		{
			client_notify( TranslateT("Login error: Captcha code is required. Bad login credentials?") );
			parent->Log(" ! !  Login error: Captcha code is required.");
			return handle_error( "login", FORCE_DISCONNECT );
		}
		
		// Get error message
		std::string error_str = utils::text::trim(
			utils::text::special_expressions_decode(
				utils::text::remove_html( 
					utils::text::edit_html(
						utils::text::source_get_value( &resp.data, 2, "id=\"standard_error\">", "</h2>" ) ) ) ) );

		if ( !error_str.length() )
			error_str = Translate("Unknown login error");
		parent->Log(" ! !  Login error: %s", error_str.c_str());

		std::string message = Translate("Login error: ") + error_str;
		TCHAR* tmessage = mir_a2t(message.c_str());
		client_notify( tmessage );
		mir_free( tmessage );
	}
	case HTTP_CODE_FORBIDDEN: // Forbidden
	case HTTP_CODE_NOT_FOUND: // Not Found
	default:
		return handle_error( "login", FORCE_DISCONNECT );

	case HTTP_CODE_FOUND: // Found and redirected to Home, Logged in, everything is OK
		if ( cookies.find("c_user") != cookies.end() )
		{
			this->self_.user_id = cookies.find("c_user")->second;
			DBWriteContactSettingString(NULL,parent->m_szModuleName,FACEBOOK_KEY_ID,this->self_.user_id.c_str());
			parent->Log("      Got self user id: %s", this->self_.user_id.c_str());
			return handle_success( "login" );
		} else {
			client_notify(TranslateT("Login error, probably bad login credentials."));
			parent->Log(" ! !  Login error, probably bad login credentials.");
			return handle_error( "login", FORCE_DISCONNECT );
		}
	}
}
Example #7
0
bool facebook_client::send_message( std::string message_recipient, std::string message_text, std::string *error_text, bool use_inbox )
{
	handle_entry( "send_message" );

	http::response resp;

	if (parent->isInvisible() || use_inbox) {
		// Use inbox send message when invisible
		std::string data = "action=send&body=";
		data += utils::url::encode( message_text );
		data += "&recipients[0]=";
		data += message_recipient;
		data += "&lsd=&fb_dtsg=";
		data += ( dtsg_.length( ) ) ? dtsg_ : "0";
		data += "&post_form_id=";
		data += ( post_form_id_.length( ) ) ? post_form_id_ : "0";

		resp = flap( FACEBOOK_REQUEST_ASYNC, &data );	
	} else {
		// Use standard send message
		std::string data = "msg_text=";
		data += utils::url::encode( message_text );
		data += "&msg_id=";
		data += utils::time::mili_timestamp( );
		data += "%3A";
		data += utils::time::unix_timestamp( );
		data += "&to=";
		data += message_recipient;
		data += "&__user="******"&client_time=";
		data += utils::time::mili_timestamp( );
		data += "&pvs_time&fb_dtsg=";
		data += ( dtsg_.length( ) ) ? dtsg_ : "0";
		data += "&to_offline=false&to_idle=false&lsd&post_form_id_source=AsyncRequest&num_tabs=1";
		data += "&window_id=0&sidebar_launched=false&sidebar_enabled=false&sidebar_capable=false&sidebar_should_show=false&sidebar_visible=false";
		data += "&post_form_id=";
		data += ( post_form_id_.length( ) ) ? post_form_id_ : "0";

		resp = flap( FACEBOOK_REQUEST_MESSAGE_SEND, &data );
	}

	
	validate_response(&resp);
	*error_text = resp.error_text;

	switch ( resp.error_number )
	{
  	case 0: // Everything is OK
		break;

    //case 1356002: // You are offline - wtf??

	case 1356003: // Contact is offline
	{
		HANDLE hContact = parent->ContactIDToHContact( message_recipient );
		if (hContact != NULL)
  			DBWriteContactSettingWord(hContact,parent->m_szModuleName,"Status",ID_STATUS_OFFLINE);
		return false;
	} break;

  	case 1356026: // Contact has alternative client
	{
		client_notify(TranslateT("Need confirmation for sending messages to other clients.\nOpen facebook website and try to send message to this contact again!"));
      /*
          post na url http://www.facebook.com/ajax/chat/post_application_settings.php?__a=1

          enable_and_send      Povolit a odeslat                                                                                                                                                                                                                                                                                                                                                                                                                               
          to_send              AQCoweMPeszBoKpd4iahcOyhmh0kiTYIhv1b5wCtuBiD0AaPVZIdEp3Pf5JMBmQ-9wf0ju-xdi-VRuk0ERk_I7XzI5dVJCs6-B0FExTZhspD-4-kTZLmZI-_M6fIuF2328yMyT3R3UEUmMV8P9MHcZwu-_pS3mOhsaHf6rIVcQ2rocSqLKi03wLKCfg0m8VsptPADWpOI-UNcIo-xl1PAoC1yVnL2wEXEtnF1qI_xFcmlJZ40AOONfIF_LS_lBrGYA-oCWLUK-GLHtQAHjO8aDeNXDU8Jk7Z_ES-_oAHee2PVLHcG_ACHXpasE7Iu3XFLMrdN2hjM96AjPRIf0Vk8gBZzfW_lUspakZmXxMI7iSNQE8lourK_6B3Z1s4UHxDZCNXYuc9gh70nm_xnaxnF9K1bR00s4MltnFjUT_3ypThzA  
          __d                  1                                                                                                                                                                                                                                                                                                                                                                                                                                               
          post_form_id         c73ebd9d94b7449c40e6965410fcdcf6                                                                                                                                                                                                                                                                                                                                                                                                                
          fb_dtsg              Tb-T9                                                                                                                                                                                                                                                                                                                                                                                                                                           
          lsd                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
          post_form_id_source  AsyncRequest                                                                                                                                                                                                                                                                                                                                                                                                                                    
          */
		return false;
	} break;
 
    default: // Other error
		return false;
 	}

	switch ( resp.code )
	{
	case HTTP_CODE_OK:
		return handle_success( "send_message" );

	case HTTP_CODE_FAKE_ERROR:
	case HTTP_CODE_FAKE_DISCONNECTED:
	default:
		*error_text = Translate("Timeout when sending message.");

		handle_error( "send_message" );
		return false;
	}
}
Example #8
0
static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                                 int len) {
        int r = 0, notify_event = 0;

        assert(client);
        assert(client->event);
        assert(message);

        if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
                log_dhcp_client(client, "not a DHCP message: ignoring");
                return 0;
        }

        if (message->op != BOOTREPLY) {
                log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
                return 0;
        }

        if (be32toh(message->xid) != client->xid) {
                log_dhcp_client(client, "received xid (%u) does not match "
                                "expected (%u): ignoring",
                                be32toh(message->xid), client->xid);
                return 0;
        }

        if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
                log_dhcp_client(client, "not an ethernet packet");
                return 0;
        }

        if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
                   ETH_ALEN)) {
                log_dhcp_client(client, "received chaddr does not match "
                                "expected: ignoring");
                return 0;
        }

        switch (client->state) {
        case DHCP_STATE_SELECTING:

                r = client_handle_offer(client, message, len);
                if (r >= 0) {

                        client->timeout_resend =
                                sd_event_source_unref(client->timeout_resend);

                        client->state = DHCP_STATE_REQUESTING;
                        client->attempt = 1;

                        r = sd_event_add_time(client->event,
                                              &client->timeout_resend,
                                              CLOCK_MONOTONIC,
                                              0, 0,
                                              client_timeout_resend, client);
                        if (r < 0)
                                goto error;

                        r = sd_event_source_set_priority(client->timeout_resend,
                                                         client->event_priority);
                        if (r < 0)
                                goto error;
                } else if (r == -ENOMSG)
                        /* invalid message, let's ignore it */
                        return 0;

                break;

        case DHCP_STATE_REBOOTING:
        case DHCP_STATE_REQUESTING:
        case DHCP_STATE_RENEWING:
        case DHCP_STATE_REBINDING:

                r = client_handle_ack(client, message, len);
                if (r == DHCP_EVENT_NO_LEASE) {

                        client->timeout_resend =
                                sd_event_source_unref(client->timeout_resend);

                        if (client->state == DHCP_STATE_REBOOTING) {
                                r = client_initialize(client);
                                if (r < 0)
                                        goto error;

                                r = client_start(client);
                                if (r < 0)
                                        goto error;

                                log_dhcp_client(client, "REBOOTED");
                        }

                        goto error;
                } else if (r >= 0) {
                        client->timeout_resend =
                                sd_event_source_unref(client->timeout_resend);

                        if (IN_SET(client->state, DHCP_STATE_REQUESTING,
                                   DHCP_STATE_REBOOTING))
                                notify_event = DHCP_EVENT_IP_ACQUIRE;
                        else if (r != DHCP_EVENT_IP_ACQUIRE)
                                notify_event = r;

                        client->state = DHCP_STATE_BOUND;
                        client->attempt = 1;

                        client->last_addr = client->lease->address;

                        r = client_set_lease_timeouts(client);
                        if (r < 0)
                                goto error;

                        if (notify_event) {
                                client = client_notify(client, notify_event);
                                if (!client ||
                                    client->state == DHCP_STATE_STOPPED)
                                        return 0;
                        }

                        client->receive_message =
                                sd_event_source_unref(client->receive_message);
                        client->fd = asynchronous_close(client->fd);
                } else if (r == -ENOMSG)
                        /* invalid message, let's ignore it */
                        return 0;

                break;

        case DHCP_STATE_INIT:
        case DHCP_STATE_INIT_REBOOT:
        case DHCP_STATE_BOUND:

                break;

        case DHCP_STATE_STOPPED:
                r = -EINVAL;
                goto error;
        }

error:
        if (r < 0 || r == DHCP_EVENT_NO_LEASE)
                client_stop(client, r);

        return r;
}
Example #9
0
bool facebook_client::home()
{
	handle_entry("home");

	// get fb_dtsg
	http::response resp = flap(REQUEST_DTSG);

	// Check whether HTTPS connection is required and we don't have it enabled
	if (!this->https_ && resp.headers["Location"].find("https://") != std::string::npos) {
		client_notify(TranslateT("Your account requires HTTPS connection. Activating."));
		parent->setByte(FACEBOOK_KEY_FORCE_HTTPS, 1);
		this->https_ = true;
		return home();
	}

	this->dtsg_ = utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");
	parent->debugLogA("      Got self dtsg: %s", this->dtsg_.c_str());

	if (this->dtsg_.empty())
		return false;
		
	resp = flap(REQUEST_HOME);

	switch (resp.code)
	{
	case HTTP_CODE_OK:
	{		
		// Get real name
		this->self_.real_name = utils::text::source_get_value(&resp.data, 2, "<strong class=\"profileName\">", "</strong>");
		
		// Try to get name again, if we've got some some weird version of Facebook
		if (this->self_.real_name.empty())
			this->self_.real_name = utils::text::source_get_value(&resp.data, 4, "id=\"root", "<strong", ">", "</strong>");

		// Get and strip optional nickname
		std::string::size_type pos = this->self_.real_name.find("<span class=\"alternate_name\">");
		if (pos != std::string::npos) {
			this->self_.nick = utils::text::source_get_value(&this->self_.real_name, 2, "<span class=\"alternate_name\">(", ")</span>");
			parent->debugLogA("      Got self nick name: %s", this->self_.nick.c_str());

			this->self_.real_name = this->self_.real_name.substr(0, pos - 1);
		}
		parent->debugLogA("      Got self real name: %s", this->self_.real_name.c_str());

		if (this->self_.real_name.empty()) {
			client_notify(TranslateT("Something happened to Facebook. Maybe there was some major update so you should wait for an update."));
			return handle_error("home", FORCE_QUIT);
		}

		// Save name and nickname
		parent->SaveName(NULL, &this->self_);

		// Get avatar
		this->self_.image_url = utils::text::source_get_value(&resp.data, 3, "class=\"l\"", "<img src=\"", "\"");
		parent->debugLogA("      Got self avatar: %s", this->self_.image_url.c_str());
		parent->CheckAvatarChange(NULL, this->self_.image_url);

		// Get logout hash
		this->logout_hash_ = utils::text::source_get_value2(&resp.data, "/logout.php?h=", "&\"");
		parent->debugLogA("      Got self logout hash: %s", this->logout_hash_.c_str());

		return handle_success("home");
	}
	case HTTP_CODE_FOUND:
		// Work-around for replica_down, f**king hell what's that?
		parent->debugLogA("      REPLICA_DOWN is back in force!");
		return this->home();
	
	default:
		return handle_error("home", FORCE_QUIT);
	}
}
Example #10
0
bool facebook_client::login(const char *username, const char *password)
{
	handle_entry("login");

	username_ = username;
	password_ = password;
	
	if (cookies.empty()) {
		// Set device ID
		ptrA device( parent->getStringA(FACEBOOK_KEY_DEVICE_ID));
		if (device != NULL)
			cookies["datr"] = device;

		// Get initial cookies
		flap(REQUEST_HOME);
	}

	// Prepare login data
	std::string data = "persistent=1";
	data += "&email=" + utils::url::encode(username);
	data += "&pass="******"&locale=" + std::string(locale);

	// Send validation
	http::response resp = flap(REQUEST_LOGIN, &data);

	// Save Device ID
	if (!cookies["datr"].empty())
		parent->setString(FACEBOOK_KEY_DEVICE_ID, cookies["datr"].c_str());

	if (resp.code == HTTP_CODE_FOUND && resp.headers.find("Location") != resp.headers.end())
	{
		// Check for invalid requests
		if (resp.headers["Location"].find("invalid_request.php") != std::string::npos) {
			client_notify(TranslateT("Login error: Invalid request."));
			parent->debugLogA(" ! !  Login error: Invalid request.");
			return handle_error("login", FORCE_QUIT);
		}

		// Check whether some Facebook things are required
		if (resp.headers["Location"].find("help.php") != std::string::npos)
		{
			client_notify(TranslateT("Login error: Some Facebook things are required."));
			parent->debugLogA(" ! !  Login error: Some Facebook things are required.");
			// return handle_error("login", FORCE_QUIT);
		}
		
		// Check whether setting Machine name is required
		if (resp.headers["Location"].find("/checkpoint/") != std::string::npos)
		{
			resp = flap(REQUEST_SETUP_MACHINE, NULL, NULL, REQUEST_GET);

			if (resp.data.find("login_approvals_no_phones") != std::string::npos) {
				// Code approval - but no phones in account
				loginError(parent, utils::text::source_get_value(&resp.data, 4, "login_approvals_no_phones", "<div", ">", "</div>"));
				return handle_error("login", FORCE_QUIT);
			}

			std::string inner_data;
			if (resp.data.find("name=\"submit[Continue]\"") != std::string::npos) {
				
				// Check if we need to approve also last unapproved device
				if (resp.data.find("name=\"name_action_selected\"") == std::string::npos) {
					// 1) Continue
					inner_data = "submit[Continue]=Continue";
					inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
					inner_data += "&fb_dtsg=" + utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");
					resp = flap(REQUEST_SETUP_MACHINE, &inner_data);

					// 2) Approve last unknown login
					// inner_data = "submit[I%20don't%20recognize]=I%20don't%20recognize"; // Don't recognize - this will force to change account password
					inner_data = "submit[This%20is%20Okay]=This%20is%20Okay"; // Recognize
					inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
					inner_data += "&fb_dtsg=" + utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");
					resp = flap(REQUEST_SETUP_MACHINE, &inner_data);

					// 3) Save last device
					inner_data = "submit[Continue]=Continue";
					inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
					inner_data += "&fb_dtsg=" + utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");
					inner_data += "&name_action_selected=save_device"; // Save device - or "dont_save"
					resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
				}

				// Save this actual device
				inner_data = "submit[Continue]=Continue";
				inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
				inner_data += "&fb_dtsg=" + utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");
				inner_data += "&name_action_selected=save_device"; // Save device - or "dont_save"
				resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
			}

			// Save actual machine name
			// inner_data = "machine_name=Miranda%20NG&submit[Don't%20Save]=Don't%20Save"; // Don't save
			inner_data = "machine_name=Miranda%20NG&submit[Save%20Device]=Save%20Device"; // Save
			inner_data += "&lsd=" + utils::text::source_get_value(&resp.data, 3, "name=\"lsd\"", "value=\"", "\"");
			inner_data += "&nh=" + utils::text::source_get_value(&resp.data, 3, "name=\"nh\"", "value=\"", "\"");
			inner_data += "&fb_dtsg=" + utils::text::source_get_value(&resp.data, 3, "name=\"fb_dtsg\"", "value=\"", "\"");

			resp = flap(REQUEST_SETUP_MACHINE, &inner_data);
		}
	}

	switch (resp.code)
	{
	case HTTP_CODE_FAKE_DISCONNECTED:
	{
		// When is error only because timeout, try login once more
		if (handle_error("login"))
			return login(username, password);
		else
			return handle_error("login", FORCE_QUIT);
	}

	case HTTP_CODE_OK: // OK page returned, but that is regular login page we don't want in fact
	{ 
		// Check whether captcha code is required
		if (resp.data.find("id=\"captcha\"") != std::string::npos)
		{
			client_notify(TranslateT("Login error: Captcha code is required. Bad login credentials?"));
			parent->debugLogA(" ! !  Login error: Captcha code is required.");
			return handle_error("login", FORCE_QUIT);
		}

		// Get and notify error message
		loginError(parent, utils::text::source_get_value(&resp.data, 4, "login_error_box", "<div", ">", "</div>")); 
	}
	case HTTP_CODE_FORBIDDEN: // Forbidden
	case HTTP_CODE_NOT_FOUND: // Not Found
	default:
		return handle_error("login", FORCE_QUIT);

	case HTTP_CODE_FOUND: // Found and redirected to Home, Logged in, everything is OK
	{
		if (cookies.find("c_user") != cookies.end()) {
			this->self_.user_id = cookies.find("c_user")->second;
			parent->setString(FACEBOOK_KEY_ID, this->self_.user_id.c_str());
			parent->debugLogA("      Got self user id: %s", this->self_.user_id.c_str());
			return handle_success("login");
		} else {
			client_notify(TranslateT("Login error, probably bad login credentials."));
			parent->debugLogA(" ! !  Login error, probably bad login credentials.");
			return handle_error("login", FORCE_QUIT);
		}
	}
	}
}
Example #11
0
http::response facebook_client::flap(RequestType request_type, std::string* request_data, std::string* request_get_data, int method)
{
	NETLIBHTTPREQUEST nlhr = {sizeof(NETLIBHTTPREQUEST)};
	nlhr.requestType = !method ? choose_method(request_type) : method;
	
	std::string url = choose_proto(request_type);
	url.append(choose_server(request_type, request_data, request_get_data));
	url.append(choose_action(request_type, request_data, request_get_data));

	nlhr.szUrl = (char*)url.c_str();
	nlhr.flags = NLHRF_HTTP11 | choose_security_level(request_type);
	nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount);

	#ifdef _DEBUG 
		nlhr.flags |= NLHRF_DUMPASTEXT;
	#else
		nlhr.flags |= NLHRF_NODUMP;
	#endif
	
	switch (request_type)
	{
	case REQUEST_MESSAGES_RECEIVE:
		nlhr.timeout = 1000 * 65; break;
	default:
		nlhr.timeout = 1000 * 20; break;
	}

	if (request_data != NULL)
	{
		nlhr.pData = (char*)(*request_data).c_str();
		nlhr.dataLength = (int)request_data->length();
	}

	parent->debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl);

	switch (request_type)
	{
	case REQUEST_LOGIN:
		nlhr.nlc = NULL;
		break;

	case REQUEST_MESSAGES_RECEIVE:
		nlhr.nlc = hMsgCon;
		nlhr.flags |= NLHRF_PERSISTENT;
		break;

	default:
		WaitForSingleObject(fcb_conn_lock_, INFINITE);
		nlhr.nlc = hFcbCon;
		nlhr.flags |= NLHRF_PERSISTENT;
		break;
	}

	NETLIBHTTPREQUEST* pnlhr = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)handle_, (LPARAM)&nlhr);

	mir_free(nlhr.headers[3].szValue);
	mir_free(nlhr.headers);

	http::response resp;

	switch (request_type)
	{
	case REQUEST_LOGIN:
	case REQUEST_SETUP_MACHINE:
		break;

	case REQUEST_MESSAGES_RECEIVE:
		hMsgCon = pnlhr ? pnlhr->nlc : NULL;
		break;

	default:
		ReleaseMutex(fcb_conn_lock_);
		hFcbCon = pnlhr ? pnlhr->nlc : NULL;
		break;
	}

	if (pnlhr != NULL)
	{
		parent->debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode);
		store_headers(&resp, pnlhr->headers, pnlhr->headersCount);
		resp.code = pnlhr->resultCode;
		resp.data = pnlhr->pData ? pnlhr->pData : "";

		CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)pnlhr);
	} else {
		parent->debugLogA("!!!!! No response from server (time-out)");
		resp.code = HTTP_CODE_FAKE_DISCONNECTED;
		// Better to have something set explicitely as this value is compaired in all communication requests
	}

	// Get Facebook's error message
	if (resp.code == HTTP_CODE_OK) {
		std::string::size_type pos = resp.data.find("\"error\":");
		if (pos != std::string::npos) {
			pos += 8;
			int error_num = atoi(resp.data.substr(pos, resp.data.find(",", pos) - pos).c_str());
			if (error_num != 0) {
				std::string error = "";

				pos = resp.data.find("\"errorDescription\":\"", pos);
				if (pos != std::string::npos) {
					pos += 20;
					error = resp.data.substr(pos, resp.data.find("\"", pos) - pos);
					error = utils::text::trim(utils::text::special_expressions_decode(utils::text::slashu_to_utf8(error)));
					error = ptrA( mir_utf8decodeA(error.c_str()));	
				}

				std::string title = "";
				pos = resp.data.find("\"errorSummary\":\"", pos);
				if (pos != std::string::npos) {
					pos += 16;
					title = resp.data.substr(pos, resp.data.find("\"", pos) - pos);
					title = utils::text::trim(utils::text::special_expressions_decode(utils::text::slashu_to_utf8(title)));
					title = ptrA( mir_utf8decodeA(title.c_str()));	
				}

				bool silent = resp.data.find("\"silentError\":1") != std::string::npos;

				resp.error_number = error_num;
				resp.error_text = error;
				resp.error_title = title;
				resp.code = HTTP_CODE_FAKE_ERROR;

				parent->debugLogA(" ! !  Received Facebook error: %d -- %s", error_num, error.c_str());
				if (notify_errors(request_type) && !silent)
					client_notify(_A2T(error.c_str()));
			}
		}
	}

	return resp;
}
Example #12
0
bool facebook_client::send_message(MCONTACT hContact, std::string message_recipient, std::string message_text, std::string *error_text, MessageMethod method)
{
	ScopedLock s(send_message_lock_);

	handle_entry("send_message");

	http::response resp;

	switch (method) {
		case MESSAGE_INBOX:
		{
			parent->debugLogA("    > Sending message through INBOX");
			std::string data = "action=send";
			data += "&body=" + utils::url::encode(message_text);
			data += "&recipients[0]=" + message_recipient;
			data += "&__user="******"&__a=1";
			data += "&fb_dtsg=" + (!dtsg_.empty() ? dtsg_ : "0");
			data += "&phstamp=0";

			resp = flap(REQUEST_MESSAGE_SEND2, &data);
			break;
		}
		case MESSAGE_MERCURY:
		{
			parent->debugLogA("    > Sending message through CHAT");
			std::string data = "message_batch[0][action_type]=ma-type:user-generated-message";
			data += "&message_batch[0][thread_id]";
			data += "&message_batch[0][author]=fbid:" + this->self_.user_id;
			data += "&message_batch[0][author_email]";
			data += "&message_batch[0][coordinates]";
			data += "&message_batch[0][timestamp]=" + utils::time::mili_timestamp();
			data += "&message_batch[0][timestamp_absolute]";
			data += "&message_batch[0][timestamp_relative]";
			data += "&message_batch[0][is_unread]=false";
			data += "&message_batch[0][is_cleared]=false";
			data += "&message_batch[0][is_forward]=false";
			data += "&message_batch[0][spoof_warning]=false";
			data += "&message_batch[0][source]=source:chat:web";
			data += "&message_batch[0][source_tags][0]=source:chat";
			data += "&message_batch[0][body]=" + utils::url::encode(message_text);
			data += "&message_batch[0][has_attachment]=false";
			data += "&message_batch[0][html_body]=false";
			data += "&message_batch[0][specific_to_list][0]=fbid:" + message_recipient;
			data += "&message_batch[0][specific_to_list][1]=fbid:" + this->self_.user_id;
			data += "&message_batch[0][status]=0";
			data += "&message_batch[0][message_id]";
			data += "&message_batch[0][client_thread_id]=user:"******"&client=mercury";
			data += "&fb_dtsg=" + (!dtsg_.empty() ? dtsg_ : "0");
			data += "&__user="******"&__a=1";
			data += "&phstamp=0";

			resp = flap(REQUEST_MESSAGE_SEND, &data);
			break;
		}
		case MESSAGE_TID:
		{
			parent->debugLogA("    > Sending message through MERCURY (TID)");
			std::string data = "message_batch[0][action_type]=ma-type:user-generated-message";
			data += "&message_batch[0][thread_id]=" + message_recipient;
			data += "&message_batch[0][author]=fbid:" + this->self_.user_id;
			data += "&message_batch[0][timestamp]=" + utils::time::mili_timestamp();
			data += "&message_batch[0][timestamp_absolute]=";
			data += "&message_batch[0][timestamp_relative]=";
			data += "&message_batch[0][is_unread]=false";
			data += "&message_batch[0][is_cleared]=false";
			data += "&message_batch[0][is_forward]=false";
			data += "&message_batch[0][source]=source:chat:web";
			data += "&message_batch[0][body]=" + utils::url::encode(message_text);
			data += "&message_batch[0][has_attachment]=false";
			data += "&message_batch[0][is_html]=false";
			data += "&message_batch[0][message_id]=";
			data += "&fb_dtsg=" + (!dtsg_.empty() ? dtsg_ : "0");
			data += "&__user="******"&phstamp=0";

			resp = flap(REQUEST_MESSAGE_SEND, &data);
			break;
		}
		case MESSAGE_ASYNC:
		{
			parent->debugLogA("    > Sending message through ASYNC");
			std::string data = "action=send";
			data += "&body=" + utils::url::encode(message_text);
			data += "&recipients[0]=" + message_recipient;
			data += "&lsd=";
			data += "&fb_dtsg=" + (!dtsg_.empty() ? dtsg_ : "0");

			resp = flap(REQUEST_ASYNC, &data);
			break;
		}
	}
	
	*error_text = resp.error_text;

	switch (resp.error_number)
	{
  	case 0: // Everything is OK
	{
		// Remember this message id
		std::string mid = utils::text::source_get_value(&resp.data, 2, "\"message_id\":\"", "\"");
		parent->setString(hContact, FACEBOOK_KEY_MESSAGE_ID, mid.c_str());
		messages_ignore.insert(std::make_pair(mid, false));
	} break;

    //case 1356002: // You are offline - wtf??

	case 1356003: // Contact is offline
	{
		MCONTACT hContact = parent->ContactIDToHContact(message_recipient);
		if (hContact != NULL)
  			parent->setWord(hContact, "Status", ID_STATUS_OFFLINE);
		return false;
	} break;

  	case 1356026: // Contact has alternative client
	{
		client_notify(TranslateT("Need confirmation for sending messages to other clients.\nOpen Facebook website and try to send message to this contact again!"));
		return false;
	} break;
 
    default: // Other error
		parent->debugLogA(" !!!  Send message error #%d: %s", resp.error_number, resp.error_text);
		return false;
 	}

	switch (resp.code)
	{
	case HTTP_CODE_OK:
		return handle_success("send_message");

	case HTTP_CODE_FAKE_ERROR:
	case HTTP_CODE_FAKE_DISCONNECTED:
	default:
		*error_text = Translate("Timeout when sending message.");

		handle_error("send_message");
		return false;
	}
}