From 3545c5a4bf039680f7d7a5cdd6cac9d19ae084c3 Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Wed, 3 Jun 2015 07:08:43 +0000 Subject: SkypeWeb: M$ account login support part 1. git-svn-id: http://svn.miranda-ng.org/main/trunk@13979 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/src/requests/login.h | 41 +++++++++++++++++++ protocols/SkypeWeb/src/skype_login.cpp | 72 ++++++++++++++++++++++++++++++++- protocols/SkypeWeb/src/skype_proto.cpp | 8 +++- protocols/SkypeWeb/src/skype_proto.h | 4 ++ protocols/SkypeWeb/src/skype_utils.cpp | 20 +++++++++ 5 files changed, 143 insertions(+), 2 deletions(-) (limited to 'protocols') diff --git a/protocols/SkypeWeb/src/requests/login.h b/protocols/SkypeWeb/src/requests/login.h index 0b7ab60d29..eb8108cabf 100644 --- a/protocols/SkypeWeb/src/requests/login.h +++ b/protocols/SkypeWeb/src/requests/login.h @@ -40,4 +40,45 @@ public: } }; +class LoginOAuthRPSRequest : public HttpRequest +{ +public: + LoginOAuthRPSRequest(const char *token) : + HttpRequest(REQUEST_POST, "api.skype.com/login/skypetoken") + { + Body + << CHAR_VALUE("scopes", "client") + << CHAR_VALUE("clientVersion", "0/7.4.85.102/259/") + << CHAR_VALUE("access_token", token) + << INT_VALUE("partner", 999); + } +}; + +class LoginMSRequest : public HttpRequest +{ +public: + LoginMSRequest() : HttpRequest(REQUEST_GET, "login.live.com/oauth20_authorize.srf") + { + + Url + << CHAR_VALUE("client_id", "00000000480BC46C") + << CHAR_VALUE("scope", "service::skype.com::MBI_SSL") + << CHAR_VALUE("response_type", "token") + << CHAR_VALUE("redirect_uri", ptrA(mir_urlEncode("https://login.live.com/oauth20_desktop.srf"))); + } + + LoginMSRequest(const char *ppft, const char* login, const char* password, const char *cookies) : + HttpRequest(REQUEST_POST, "https://login.live.com/ppsecure/post.srf") + { + Headers + << CHAR_VALUE("Content-Type", "application/x-www-form-urlencoded") + << CHAR_VALUE("Cookie", cookies); + + Body + << CHAR_VALUE("PPFT", ptrA(mir_urlEncode(ppft))) + << CHAR_VALUE("login", ptrA(mir_urlEncode(login))) + << CHAR_VALUE("passwd", ptrA(mir_urlEncode(password))); + } +}; + #endif //_SKYPE_REQUEST_LOGIN_H_ diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp index 2de32f82be..ad6eab4769 100644 --- a/protocols/SkypeWeb/src/skype_login.cpp +++ b/protocols/SkypeWeb/src/skype_login.cpp @@ -17,9 +17,79 @@ along with this program. If not, see . #include "stdafx.h" +void CSkypeProto::OnLoginMSFirst(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL || response->pData == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + std::string content = response->pData; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + } + std::string pie = match[1]; + + for (int i = 0; i < response->headersCount; i++) + { + if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + continue; + + regex = "^(.+?)=(.+?);"; + content = response->headers[i].szValue; + + if (std::regex_search(content, match, regex)) + cookies[match[1]] = match[2]; + } + + CMStringA allCookies; + if (!cookies.empty()) + { + for (std::map::iterator cookie = cookies.begin(); cookie != cookies.end(); ++cookie) + allCookies.AppendFormat("%s=%s; ", cookie->first.c_str(), cookie->second.c_str()); + } + + SendRequest(new LoginMSRequest(pie.c_str(), ptrA(getStringA(SKYPE_SETTINGS_ID)), ptrA(getStringA(SKYPE_SETTINGS_PASSWORD)), allCookies.GetBuffer()), &CSkypeProto::OnLoginMSSecond); +} + +void CSkypeProto::OnLoginMSSecond(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL || response->pData == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + std::string content = response->pData, token; + + for (int i = 0; i < response->headersCount; i++) + { + if (!mir_strcmpi(response->headers[i].szName, "Location")) + { + regex = "access_token=(.+?)&"; + content = response->headers[i].szValue; + + if (std::regex_search(content, match, regex)) + token = urlDecode(match[1]); + } + } + SendRequest(new LoginOAuthRPSRequest(token.c_str()), &CSkypeProto::OnLoginOAuth); +} + void CSkypeProto::OnLoginOAuth(const NETLIBHTTPREQUEST *response) { - if (response == NULL) + if (response == NULL || response->pData == NULL) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index 4b72a863ee..602ae7144f 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -255,7 +255,13 @@ int CSkypeProto::SetStatus(int iNewStatus) if ((tokenExpires - 1800) > time(NULL)) OnLoginSuccess(); else - SendRequest(new LoginOAuthRequest(ptrA(getStringA(SKYPE_SETTINGS_ID)), ptrA(getStringA(SKYPE_SETTINGS_PASSWORD))), &CSkypeProto::OnLoginOAuth); + { + if (strstr(ptrA(getStringA(SKYPE_SETTINGS_ID)), "@")) + SendRequest(new LoginMSRequest(), &CSkypeProto::OnLoginMSFirst); + else + SendRequest(new LoginOAuthRequest(ptrA(getStringA(SKYPE_SETTINGS_ID)), ptrA(getStringA(SKYPE_SETTINGS_PASSWORD))), &CSkypeProto::OnLoginOAuth); + + } } else { diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 6a16d06939..faf3808607 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -171,6 +171,8 @@ private: int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam); // login + void OnLoginMSFirst(const NETLIBHTTPREQUEST *response); + void OnLoginMSSecond(const NETLIBHTTPREQUEST *response); void OnLoginOAuth(const NETLIBHTTPREQUEST *response); void OnLoginSuccess(); void OnEndpointCreated(const NETLIBHTTPREQUEST *response); @@ -337,6 +339,8 @@ private: time_t GetLastMessageTime(MCONTACT hContact); + std::string urlDecode(std::string SRC); + //events void InitDBEvents(); int __cdecl ProcessSrmmEvent(WPARAM, LPARAM); diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index fe55c22841..d84fc3d86e 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -784,4 +784,24 @@ void CSkypeProto::SkypeUnsetTimer(void*) if (CSkypeProto::m_timer) KillTimer(NULL, CSkypeProto::m_timer); CSkypeProto::m_timer = 0; +} + +std::string CSkypeProto::urlDecode(std::string SRC) +{ + std::string ret; + char ch; + int i, ii; + for (i = 0; i < SRC.length(); i++) + { + if (int(SRC[i]) == 37) + { + sscanf(SRC.substr(i + 1, 2).c_str(), "%x", &ii); + ch = static_cast(ii); + ret += ch; + i = i + 2; + } + else + ret += SRC[i]; + } + return (ret); } \ No newline at end of file -- cgit v1.2.3