diff options
author | Robert Pösel <robyer@seznam.cz> | 2013-06-20 14:33:13 +0000 |
---|---|---|
committer | Robert Pösel <robyer@seznam.cz> | 2013-06-20 14:33:13 +0000 |
commit | d309cbb26087c407d0f410e80a9b71e38389439d (patch) | |
tree | 833e7d0176442852acb7a31092eba4c29d2ee65d | |
parent | 5dc50515b56903ad73c811184b0ac8b5df6d1725 (diff) |
Facebook: Login procedure improvements.
- fixed approving last device
- supporting security features (successful login after approved this unknown device by browser - BUT you must logout and login in your browser for correct approval! (fb bug))
- some other fixes
git-svn-id: http://svn.miranda-ng.org/main/trunk@5068 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r-- | protocols/FacebookRM/src/client.h | 5 | ||||
-rw-r--r-- | protocols/FacebookRM/src/communication.cpp | 123 | ||||
-rw-r--r-- | protocols/FacebookRM/src/connection.cpp | 8 | ||||
-rw-r--r-- | protocols/FacebookRM/src/proto.cpp | 9 |
4 files changed, 78 insertions, 67 deletions
diff --git a/protocols/FacebookRM/src/client.h b/protocols/FacebookRM/src/client.h index 621326ac3c..024ba16b26 100644 --- a/protocols/FacebookRM/src/client.h +++ b/protocols/FacebookRM/src/client.h @@ -22,7 +22,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #pragma once
-#define FORCE_DISCONNECT true
+#define FORCE_DISCONNECT 1
+#define FORCE_QUIT 2
class facebook_client
{
@@ -110,7 +111,7 @@ public: bool handle_entry(std::string method);
bool handle_success(std::string method);
- bool handle_error(std::string method, bool force_disconnect = false);
+ bool handle_error(std::string method, int force_disconnect = 0);
void __inline increment_error() { this->error_count_++; }
void __inline decrement_error() { if (error_count_ > 0) error_count_--; }
diff --git a/protocols/FacebookRM/src/communication.cpp b/protocols/FacebookRM/src/communication.cpp index 39cc38d5b2..2f6a78f217 100644 --- a/protocols/FacebookRM/src/communication.cpp +++ b/protocols/FacebookRM/src/communication.cpp @@ -184,23 +184,20 @@ bool facebook_client::handle_success(std::string method) return true;
}
-bool facebook_client::handle_error(std::string method, bool force_disconnect)
+bool facebook_client::handle_error(std::string method, int action)
{
- bool result;
increment_error();
parent->Log("!!!!! %s(): Something with Facebook went wrong", method.c_str());
- if (force_disconnect)
- result = false;
- else if (error_count_ <= (UINT)db_get_b(NULL,parent->m_szModuleName,FACEBOOK_KEY_TIMEOUTS_LIMIT,FACEBOOK_TIMEOUTS_LIMIT))
- result = true;
- else
+ bool result = (error_count_ <= (UINT)db_get_b(NULL,parent->m_szModuleName,FACEBOOK_KEY_TIMEOUTS_LIMIT,FACEBOOK_TIMEOUTS_LIMIT));
+ if (action == FORCE_DISCONNECT || action == FORCE_QUIT)
result = false;
- if (result == false)
- {
+ if (!result) {
reset_error();
- parent->SetStatus(ID_STATUS_OFFLINE);
+
+ if (action != FORCE_QUIT)
+ parent->SetStatus(ID_STATUS_OFFLINE);
}
return result;
@@ -632,6 +629,20 @@ void facebook_client::clear_cookies() cookies.clear();
}
+void loginError(FacebookProto *proto, std::string error_str) {
+ error_str = utils::text::trim(
+ utils::text::special_expressions_decode(
+ utils::text::remove_html(
+ utils::text::edit_html(error_str))));
+
+ proto->Log(" ! ! Login error: %s", error_str.length() ? error_str.c_str() : "Unknown error");
+
+ TCHAR buf[200];
+ mir_sntprintf(buf, SIZEOF(buf), TranslateT("Login error: %s"),
+ (!error_str.length()) ? TranslateT("Unknown error") : ptrT(mir_utf8decodeT(error_str.c_str())));
+ proto->facy.client_notify(buf);
+}
+
bool facebook_client::login(const std::string &username,const std::string &password)
{
handle_entry("login");
@@ -639,8 +650,8 @@ bool facebook_client::login(const std::string &username,const std::string &passw username_ = username;
password_ = password;
- // Access homepage to get initial cookies
- flap(FACEBOOK_REQUEST_HOME, NULL);
+ // Get initial cookies
+ flap(FACEBOOK_REQUEST_LOGIN);
// 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&pass_placeHolder=Password&login=Login&persistent=1";
@@ -657,21 +668,46 @@ bool facebook_client::login(const std::string &username,const std::string &passw // Process result data
validate_response(&resp);
+ // Save Device ID
+ if (cookies["datr"].length())
+ db_set_s(NULL, parent->m_szModuleName, 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->Log(" ! ! Login error: Invalid request.");
+ return handle_error("login", FORCE_QUIT);
+ }
+
+ // 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."));
+ db_set_b(NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS, 1);
+ this->https_ = true;
+ return login(username, password);
+ }
+
// 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);
+ // return handle_error("login", FORCE_QUIT);
}
// Check whether setting Machine name is required
if (resp.headers["Location"].find("/checkpoint/") != std::string::npos)
{
resp = flap(FACEBOOK_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) {
// Multi step with approving last unrecognized device
@@ -687,6 +723,13 @@ bool facebook_client::login(const std::string &username,const std::string &passw 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(FACEBOOK_REQUEST_SETUP_MACHINE, &inner_data);
+
+ // 3) Save 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(FACEBOOK_REQUEST_SETUP_MACHINE, &inner_data);
}
// Save actual machine name
@@ -700,25 +743,6 @@ bool facebook_client::login(const std::string &username,const std::string &passw 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."));
- db_set_b(NULL, parent->m_szModuleName, FACEBOOK_KEY_FORCE_HTTPS, 1);
- this->https_ = true;
- }
- }
-
- }
-
- // Check for Device ID
- if (cookies["datr"].length())
- db_set_s(NULL, parent->m_szModuleName, FACEBOOK_KEY_DEVICE_ID, cookies["datr"].c_str());
switch (resp.code)
{
@@ -728,7 +752,7 @@ bool facebook_client::login(const std::string &username,const std::string &passw if (handle_error("login"))
return login(username, password);
else
- return false;
+ 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
@@ -738,31 +762,19 @@ bool facebook_client::login(const std::string &username,const std::string &passw {
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);
+ return handle_error("login", FORCE_QUIT);
}
- // 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, 4, "login_error_box", "<div", ">", "</div>")))));
-
- parent->Log(" ! ! Login error: %s", error_str.length() ? error_str.c_str() : "Unknown error");
-
- TCHAR buf[200];
- mir_sntprintf(buf, SIZEOF(buf), TranslateT("Login error: %s"),
- (!error_str.length()) ? TranslateT("Unknown error") : ptrT(mir_utf8decodeT(error_str.c_str())));
- client_notify(buf);
+ // 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_DISCONNECT);
+ 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())
- {
+ if (cookies.find("c_user") != cookies.end()) {
this->self_.user_id = cookies.find("c_user")->second;
db_set_s(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());
@@ -770,7 +782,7 @@ bool facebook_client::login(const std::string &username,const std::string &passw } else {
client_notify(TranslateT("Login error, probably bad login credentials."));
parent->Log(" ! ! Login error, probably bad login credentials.");
- return handle_error("login", FORCE_DISCONNECT);
+ return handle_error("login", FORCE_QUIT);
}
}
}
@@ -809,7 +821,6 @@ bool facebook_client::home() {
handle_entry("home");
-
// get fb_dtsg
http::response resp = flap(FACEBOOK_REQUEST_DTSG);
@@ -836,7 +847,7 @@ bool facebook_client::home() 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);
+ return handle_error("home", FORCE_QUIT);
}
// Get avatar
@@ -848,9 +859,7 @@ bool facebook_client::home() this->logout_hash_ = utils::text::source_get_value2(&resp.data, "/logout.php?h=", "&\"");
parent->Log(" 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?
@@ -858,7 +867,7 @@ bool facebook_client::home() return this->home();
default:
- return handle_error("home", FORCE_DISCONNECT);
+ return handle_error("home", FORCE_QUIT);
}
}
diff --git a/protocols/FacebookRM/src/connection.cpp b/protocols/FacebookRM/src/connection.cpp index 6ba25ec470..27908aa019 100644 --- a/protocols/FacebookRM/src/connection.cpp +++ b/protocols/FacebookRM/src/connection.cpp @@ -103,6 +103,12 @@ void FacebookProto::ChangeStatus(void*) } else {
ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_FAILED, (HANDLE)old_status, m_iStatus);
+ if (facy.hFcbCon)
+ Netlib_CloseHandle(facy.hFcbCon);
+ facy.hFcbCon = NULL;
+
+ facy.clear_cookies();
+
// Set to offline
m_iStatus = m_iDesiredStatus = facy.self_.status_id = ID_STATUS_OFFLINE;
ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
@@ -185,7 +191,7 @@ bool FacebookProto::NegotiateConnection() {
CallService(MS_CLIST_GROUPCREATE, 0, (LPARAM)dbv.ptszVal);
}
-
+
return facy.login(user, pass);
}
diff --git a/protocols/FacebookRM/src/proto.cpp b/protocols/FacebookRM/src/proto.cpp index 10cf2591bf..9f37b2a8b8 100644 --- a/protocols/FacebookRM/src/proto.cpp +++ b/protocols/FacebookRM/src/proto.cpp @@ -162,11 +162,6 @@ int FacebookProto::SetStatus(int new_status) m_iDesiredStatus = new_status;
break;
- // TODO RM: needed/useful?
- case ID_STATUS_CONNECTING:
- m_iDesiredStatus = ID_STATUS_OFFLINE;
- break;
-
case ID_STATUS_IDLE:
default:
m_iDesiredStatus = ID_STATUS_INVISIBLE;
@@ -178,8 +173,8 @@ int FacebookProto::SetStatus(int new_status) break;
}
- if (m_iStatus == ID_STATUS_CONNECTING) {
- LOG("===== Status is connecting, no change");
+ if (new_status != ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_CONNECTING) {
+ LOG("===== Status is already connecting, no change");
return 0;
}
|