From 90a05404a6ded56141c0230f663686439f8fa146 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Tue, 7 Apr 2015 21:50:05 +0000 Subject: SkypeWeb: - added ability to getting contacts statuses - partly reworked login flow git-svn-id: http://svn.miranda-ng.org/main/trunk@12665 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/SkypeWeb/src/skype_login.cpp | 188 +++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 protocols/SkypeWeb/src/skype_login.cpp (limited to 'protocols/SkypeWeb/src/skype_login.cpp') diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp new file mode 100644 index 0000000000..ea5a949af0 --- /dev/null +++ b/protocols/SkypeWeb/src/skype_login.cpp @@ -0,0 +1,188 @@ +#include "common.h" + +int CSkypeProto::OnModulesLoaded(WPARAM, LPARAM) +{ + return 0; +} + +void CSkypeProto::OnLoginFirst(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + std::regex regex; + std::smatch match; + + const std::string content = response->pData; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string pie = match[1]; + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string etm = match[1]; + + ptrA skypename(mir_utf8encodeT(ptrT(getTStringA(SKYPE_SETTINGS_ID)))); + ptrA password(mir_utf8encodeT(ptrT(getTStringA(SKYPE_SETTINGS_PASSWORD)))); + + PushRequest(new LoginRequest(skypename, password, pie.c_str(), etm.c_str()), &CSkypeProto::OnLoginSecond); +} + +void CSkypeProto::OnLoginSecond(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + 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, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string token = match[1]; + setString("TokenSecret", token.c_str()); + + regex = ""; + if (!std::regex_search(content, match, regex)) + { + ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, 1001); + SetStatus(ID_STATUS_OFFLINE); + return; + } + std::string expiresIn = match[1]; + int seconds = atoi(expiresIn.c_str()); + setDword("TokenExpiresIn", time(NULL) + seconds); + + 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]; + } + + ptrA server(getStringA("Server")); + PushRequest(new CreateEndpointRequest(token.c_str()), &CSkypeProto::OnEndpointCreated); + + PushRequest(new GetProfileRequest(token.c_str()), &CSkypeProto::LoadProfile); + PushRequest(new GetContactListRequest(token.c_str()), &CSkypeProto::LoadContactList); +} + +void CSkypeProto::OnEndpointCreated(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + return; + + std::regex regex; + std::smatch match; + for (int i = 0; i < response->headersCount; i++) + { + if (!mir_strcmpi(response->headers[i].szName, "Set-RegistrationToken")) + { + CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; + int iStart = 0; + while (true) + { + CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); + if (iStart == -1) + break; + int iStart2 = 0; + szCookieName = szToken.Tokenize("=", iStart2); + szCookieVal = szToken.Mid(iStart2); + setString(szCookieName, szCookieVal); + } + } + else if (!mir_strcmpi(response->headers[i].szName, "Location")) + { + CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; + setString("Server", ptrA(GetServerFromUrl(szValue))); + } + + } + + ptrA server(getStringA("Server")); + + if (response->resultCode != 201) + { + ptrA token(getStringA("Token")); + PushRequest(new CreateEndpointRequest(token), &CSkypeProto::OnEndpointCreated); + return; + } + + ptrA regToken(getStringA("registrationToken")); + + + PushRequest(new CreateSubscriptionsRequest(regToken), &CSkypeProto::OnSubscriptionsCreated); +} + +void CSkypeProto::OnSubscriptionsCreated(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + return; + + ptrA regToken(getStringA("registrationToken")); + ptrA skypename(getStringA(SKYPE_SETTINGS_ID)); + //ptrA endpoint(getStringA("endpointId")); + //PushRequest(new SendCapabilitiesRequest(regToken, endpoint)); + //PushRequest(new SetStatusRequest(regToken, MirandaToSkypeStatus(m_iDesiredStatus)), &CSkypeProto::OnStatusChanged); + PushRequest(new GetContactStatusRequest(regToken, skypename), &CSkypeProto::OnStatusChanged); + + LIST skypenames(1); + for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) + skypenames.insert(getStringA(hContact, SKYPE_SETTINGS_ID)); + PushRequest(new CreateContactsRequest(regToken, skypenames)); + for (int i = 0; i < skypenames.getCount(); i++) + mir_free(skypenames[i]); + skypenames.destroy(); + + m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, 0, NULL); +} + +void CSkypeProto::OnStatusChanged(const NETLIBHTTPREQUEST *response) +{ + if (response == NULL) + return; + + JSONROOT root(response->pData); + + if (root == NULL) + return; + + JSONNODE *status_json = json_get(root, "status"); + ptrT status(json_as_string(status_json)); + int iNewStatus = SkypeToMirandaStatus(_T2A(status)); + + if (iNewStatus == ID_STATUS_OFFLINE) + SetStatus(ID_STATUS_OFFLINE); + + m_iStatus = m_iDesiredStatus = iNewStatus; + ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus); +} \ No newline at end of file -- cgit v1.2.3