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/SkypeWeb_12.vcxproj | 4 +- protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters | 12 +- protocols/SkypeWeb/src/common.h | 4 +- protocols/SkypeWeb/src/requests/avatars.h | 8 +- protocols/SkypeWeb/src/requests/capabilities.h | 25 ++++ protocols/SkypeWeb/src/requests/contacts.h | 33 +++++ protocols/SkypeWeb/src/requests/endpoint.h | 29 ++-- protocols/SkypeWeb/src/requests/status.h | 6 +- protocols/SkypeWeb/src/requests/subscriptions.h | 4 +- protocols/SkypeWeb/src/skype_events.cpp | 177 ---------------------- protocols/SkypeWeb/src/skype_login.cpp | 188 ++++++++++++++++++++++++ protocols/SkypeWeb/src/skype_polling.cpp | 23 ++- protocols/SkypeWeb/src/skype_proto.cpp | 12 +- protocols/SkypeWeb/src/skype_proto.h | 20 ++- protocols/SkypeWeb/src/skype_utils.cpp | 2 +- 15 files changed, 307 insertions(+), 240 deletions(-) create mode 100644 protocols/SkypeWeb/src/requests/capabilities.h delete mode 100644 protocols/SkypeWeb/src/skype_events.cpp create mode 100644 protocols/SkypeWeb/src/skype_login.cpp (limited to 'protocols') diff --git a/protocols/SkypeWeb/SkypeWeb_12.vcxproj b/protocols/SkypeWeb/SkypeWeb_12.vcxproj index fe73b7b6a7..bdf966c16d 100644 --- a/protocols/SkypeWeb/SkypeWeb_12.vcxproj +++ b/protocols/SkypeWeb/SkypeWeb_12.vcxproj @@ -204,13 +204,13 @@ + - - + diff --git a/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters b/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters index 1a1383d6b4..cbf2510819 100644 --- a/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters +++ b/protocols/SkypeWeb/SkypeWeb_12.vcxproj.filters @@ -54,12 +54,6 @@ Header Files\requests - - Header Files\requests - - - Header Files\requests - Header Files\requests @@ -81,6 +75,12 @@ Header Files\requests + + Header Files\requests + + + Header Files\requests + diff --git a/protocols/SkypeWeb/src/common.h b/protocols/SkypeWeb/src/common.h index ab5787e07f..b4a870c207 100644 --- a/protocols/SkypeWeb/src/common.h +++ b/protocols/SkypeWeb/src/common.h @@ -53,8 +53,8 @@ struct CSkypeProto; #include "requests\profile.h" #include "requests\contacts.h" #include "requests\status.h" -#include "requests\reg_info.h" #include "requests\endpoint.h" +#include "requests\capabilities.h" #include "requests\subscriptions.h" #include "requests\messages.h" #include "requests\poll.h" @@ -72,4 +72,6 @@ extern HINSTANCE g_hInstance; #define SKYPE_DB_EVENT_TYPE_ACTION 10001 +#define SKYPE_ENDPOINTS_HOST "client-s.gateway.messenger.live.com" + #endif //_COMMON_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/requests/avatars.h b/protocols/SkypeWeb/src/requests/avatars.h index 6b71a0732d..f089ae5c1b 100644 --- a/protocols/SkypeWeb/src/requests/avatars.h +++ b/protocols/SkypeWeb/src/requests/avatars.h @@ -16,13 +16,15 @@ public: SetAvatarRequest(const char *token, const char *skypename, const char *data, size_t dataSize) : HttpRequest(REQUEST_PUT, FORMAT, "api.skype.com/users/%s/profile/avatar", skypename) { - pData = (char*)mir_alloc(dataSize); - memcpy(pData, data, dataSize); - dataLength = dataSize; Headers << CHAR_VALUE("X-Skypetoken", token) << CHAR_VALUE("Content-Type", "image/jpeg"); + + pData = (char*)mir_alloc(dataSize); + memcpy(pData, data, dataSize); + dataLength = dataSize; } + ~SetAvatarRequest() { mir_free(pData); diff --git a/protocols/SkypeWeb/src/requests/capabilities.h b/protocols/SkypeWeb/src/requests/capabilities.h new file mode 100644 index 0000000000..3c2894ac91 --- /dev/null +++ b/protocols/SkypeWeb/src/requests/capabilities.h @@ -0,0 +1,25 @@ +#ifndef _SKYPE_REQUEST_CAPS_H_ +#define _SKYPE_REQUEST_CAPS_H_ + +class SendCapabilitiesRequest : public HttpRequest +{ +public: + SendCapabilitiesRequest(const char *regToken, const char *endpointID, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_PUT, FORMAT, "%s/v1/users/ME/endpoints/%s/presenceDocs/messagingService", server, ptrA(mir_urlEncode(endpointID))) + { + Headers + << CHAR_VALUE("Accept", "application/json, text/javascript") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken) + << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8"); + CMStringA data; + + int bitness = 32; +#ifdef _WIN64 + bitness = 64; +#endif + data.AppendFormat("{\"id\":\"messagingService\",\"type\":\"EndpointPresenceDoc\",\"selfLink\":\"uri\",\"privateInfo\":{\"epname\":\"Miranda\"},\"publicInfo\":{\"capabilities\":\"\",\"typ\":125,\"skypeNameVersion\":\"Miranda NG Skype\",\"nodeInfo\":\"xx\",\"version\":\"%s x%d\"}}", MIRANDA_VERSION_STRING, bitness); + Body << + VALUE(data); + } +}; +#endif //_SKYPE_REQUEST_CAPS_H_ \ No newline at end of file diff --git a/protocols/SkypeWeb/src/requests/contacts.h b/protocols/SkypeWeb/src/requests/contacts.h index 8a23526bf9..585df9a92d 100644 --- a/protocols/SkypeWeb/src/requests/contacts.h +++ b/protocols/SkypeWeb/src/requests/contacts.h @@ -30,6 +30,39 @@ public: } }; +class GetContactStatusRequest : public HttpRequest +{ +public: + GetContactStatusRequest(const char *regToken, const char *skypename, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_GET, FORMAT, "%s/v1/users/ME/contacts/8:%s/presenceDocs/messagingService", server, skypename) + { + Headers + << CHAR_VALUE("Accept", "application/json, text/javascript") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken); + } +}; + +class CreateContactsRequest : public HttpRequest +{ +public: + CreateContactsRequest(const char *regToken, const LIST &skypenames, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/contacts", server) + { + Headers + << CHAR_VALUE("Accept", "application/json, text/javascript") + << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8") + << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken); + + CMStringA data = "{\"contacts\":["; + for (int i = 0; i < skypenames.getCount(); i++) + data.AppendFormat("{\"id\":\"8:%s\"},", skypenames[i]); + data.Truncate(data.GetLength() - 1); + data.Append("]}"); + + Body << VALUE(data); + } +}; + class GetContactsAuthRequest : public HttpRequest { public: diff --git a/protocols/SkypeWeb/src/requests/endpoint.h b/protocols/SkypeWeb/src/requests/endpoint.h index 8af43de6c3..51c7e6f634 100644 --- a/protocols/SkypeWeb/src/requests/endpoint.h +++ b/protocols/SkypeWeb/src/requests/endpoint.h @@ -1,25 +1,20 @@ -#ifndef _SKYPE_REQUEST_ENDPOINT_H_ -#define _SKYPE_REQUEST_ENDPOINT_H_ +#ifndef _SKYPE_REQUEST_REGINFO_H_ +#define _SKYPE_REQUEST_REGINFO_H_ -class GetEndpointRequest : public HttpRequest +class CreateEndpointRequest : public HttpRequest { public: - GetEndpointRequest(const char *regToken, const char *endpointID, const char *server = "client-s.gateway.messenger.live.com") : - HttpRequest(REQUEST_PUT, FORMAT, "%s/v1/users/ME/endpoints/%s/presenceDocs/messagingService", server, ptrA(mir_urlEncode(endpointID))) + CreateEndpointRequest(const char *token, const char *server = "client-s.gateway.messenger.live.com") : + HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints", server) { + Headers << CHAR_VALUE("Accept", "application/json, text/javascript") - << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken) - << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8"); - CMStringA data; - - int bitness = 32; -#ifdef _WIN64 - bitness = 64; -#endif - data.AppendFormat("{\"id\":\"messagingService\",\"type\":\"EndpointPresenceDoc\",\"selfLink\":\"uri\",\"privateInfo\":{\"epname\":\"Miranda\"},\"publicInfo\":{\"capabilities\":\"\",\"typ\":125,\"skypeNameVersion\":\"Miranda NG Skype\",\"nodeInfo\":\"xx\",\"version\":\"%s x%d\"}}", MIRANDA_VERSION_STRING, bitness); - Body << - VALUE(data); + << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8") + << FORMAT_VALUE("Authentication", "skypetoken=%s", token); + + Body << VALUE("{}"); } }; -#endif //_SKYPE_REQUEST_ENDPOINT_H_ \ No newline at end of file + +#endif //_SKYPE_REQUEST_STATUS_H_ diff --git a/protocols/SkypeWeb/src/requests/status.h b/protocols/SkypeWeb/src/requests/status.h index f7669e2197..6d61af48d5 100644 --- a/protocols/SkypeWeb/src/requests/status.h +++ b/protocols/SkypeWeb/src/requests/status.h @@ -7,14 +7,14 @@ public: SetStatusRequest(const char *regToken, const char *status, const char *server = "client-s.gateway.messenger.live.com") : HttpRequest(REQUEST_PUT, FORMAT, "%s/v1/users/ME/presenceDocs/messagingService", server) { - CMStringA statuss; - statuss.AppendFormat("{\"status\":\"%s\"}", status); Headers << CHAR_VALUE("Accept", "application/json, text/javascript") << FORMAT_VALUE("RegistrationToken", "registrationToken=%s", regToken) << CHAR_VALUE("Content-Type", "application/json; charset=UTF-8"); - Body << VALUE(statuss); + CMStringA data; + data.AppendFormat("{\"status\":\"%s\"}", status); + Body << VALUE(data); } }; diff --git a/protocols/SkypeWeb/src/requests/subscriptions.h b/protocols/SkypeWeb/src/requests/subscriptions.h index 236b26f7cc..bff30fdb2e 100644 --- a/protocols/SkypeWeb/src/requests/subscriptions.h +++ b/protocols/SkypeWeb/src/requests/subscriptions.h @@ -1,10 +1,10 @@ #ifndef _SKYPE_REQUEST_SUBSCIPTIONS_H_ #define _SKYPE_REQUEST_SUBSCIPTIONS_H_ -class SubscriptionsRequest : public HttpRequest +class CreateSubscriptionsRequest : public HttpRequest { public: - SubscriptionsRequest(const char *regToken, const char *server = "client-s.gateway.messenger.live.com") : + CreateSubscriptionsRequest(const char *regToken, const char *server = "client-s.gateway.messenger.live.com") : HttpRequest(REQUEST_POST, FORMAT, "%s/v1/users/ME/endpoints/SELF/subscriptions", server) { Headers diff --git a/protocols/SkypeWeb/src/skype_events.cpp b/protocols/SkypeWeb/src/skype_events.cpp deleted file mode 100644 index f471302fda..0000000000 --- a/protocols/SkypeWeb/src/skype_events.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#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]; - } - - PushRequest(new GetRegInfoRequest(token.c_str(), getStringA("Server")), &CSkypeProto::OnGetRegInfo); - PushRequest(new GetProfileRequest(token.c_str()), &CSkypeProto::LoadProfile); - PushRequest(new GetContactListRequest(token.c_str()), &CSkypeProto::LoadContactList); -} - -void CSkypeProto::OnGetRegInfo(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", GetServerFromUrl(szValue)); - } - - } - if (response->resultCode != 201) - { - PushRequest(new GetRegInfoRequest(getStringA("Token"), getStringA("Server")), &CSkypeProto::OnGetRegInfo); - return; - } - - PushRequest(new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId"), getStringA("Server")), &CSkypeProto::OnGetEndpoint); - isTerminated = false; - m_hPollingThread = ForkThreadEx(&CSkypeProto::PollingThread, 0, NULL); - - m_iStatus = m_iDesiredStatus; - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus); - PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus), getStringA("Server")), &CSkypeProto::OnSetStatus); -} - -void CSkypeProto::OnGetEndpoint(const NETLIBHTTPREQUEST *response) -{ - if (response == NULL) - return; - - JSONROOT root(response->pData); - - if (root == NULL) - return; - - ptrA selfLink(mir_t2a(ptrT(json_as_string(json_get(root, "selfLink"))))); - - setString("SelfEndpointName", SelfUrlToName(selfLink)); -} - -void CSkypeProto::OnSetStatus(const NETLIBHTTPREQUEST *response) -{ - if (response == NULL) - return; - - JSONROOT root(response->pData); - - if (root == NULL) - return; - - JSONNODE *status_json = json_get(root, "status"); - ptrA status(mir_t2a(ptrT(json_as_string(status_json)))); - int old_status = m_iStatus; - int iNewStatus = SkypeToMirandaStatus(status); - m_iStatus = iNewStatus; - - if (iNewStatus == ID_STATUS_OFFLINE) - SetStatus(ID_STATUS_OFFLINE); - else - ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus); -} \ No newline at end of file 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 diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index ad882e10a9..fb2ea0fd7b 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -47,28 +47,27 @@ void CSkypeProto::PollingThread(void*) ptrA regToken(getStringA("registrationToken")); ptrA server(getStringA("Server")); - SubscriptionsRequest *request = new SubscriptionsRequest(regToken, server); - request->Send(m_hNetlibUser); - delete request; - int errors = 0; bool breaked = false; + isTerminated = false; while (!isTerminated && !breaked && errors < POLLING_ERRORS_LIMIT) { - PollRequest *request = new PollRequest(regToken, server); + PollRequest *request = new PollRequest(regToken); request->nlc = m_pollingConnection; NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser); - if (response != NULL) + if (response) { - JSONROOT root(response->pData); - if (json_get(root, "errorCode") != NULL) + if (response->pData) { - errors++; - continue; + JSONROOT root(response->pData); + if (json_get(root, "errorCode") != NULL) + { + errors++; + continue; + } + ParsePollData(root); } - ParsePollData (root); - errors = 0; m_pollingConnection = response->nlc; CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response); } diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index f9e43ba97c..91ab87bc78 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -149,9 +149,7 @@ int CSkypeProto::SetApparentMode(MCONTACT, int) { return 0; } int CSkypeProto::SetStatus(int iNewStatus) { if (iNewStatus == m_iDesiredStatus) - { return 0; - } debugLogA(__FUNCTION__ ": changing status from %i to %i", m_iStatus, iNewStatus); @@ -189,19 +187,17 @@ int CSkypeProto::SetStatus(int iNewStatus) else if (old_status == ID_STATUS_OFFLINE && m_iStatus == ID_STATUS_OFFLINE) { // login - if (getStringA("Server") == NULL) - setString("Server", "client-s.gateway.messenger.live.com"); m_iStatus = ID_STATUS_CONNECTING; - requestQueue->Start(); PushRequest(new LoginRequest(), &CSkypeProto::OnLoginFirst); } else { // set status - m_iStatus = iNewStatus; - PushRequest(new SetStatusRequest(ptrA(getStringA("registrationToken")), MirandaToSkypeStatus(m_iStatus), getStringA("Server")), &CSkypeProto::OnSetStatus); - PushRequest(new GetEndpointRequest(getStringA("registrationToken"), getStringA("endpointId"), getStringA("Server"))); + ptrA regToken(getStringA("registrationToken")); + ptrA endpoint(getStringA("endpointId")); + PushRequest(new SendCapabilitiesRequest(regToken, endpoint)); + PushRequest(new SetStatusRequest(regToken, MirandaToSkypeStatus(m_iDesiredStatus)), &CSkypeProto::OnStatusChanged); } } diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 08a54a9acc..7f06d05385 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -134,12 +134,13 @@ private: int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam); - // events + // login void OnLoginFirst(const NETLIBHTTPREQUEST *response); void OnLoginSecond(const NETLIBHTTPREQUEST *response); - void OnGetRegInfo(const NETLIBHTTPREQUEST *response); - void OnSetStatus(const NETLIBHTTPREQUEST *response); - void OnGetEndpoint(const NETLIBHTTPREQUEST *response); + void OnEndpointCreated(const NETLIBHTTPREQUEST *response); + void OnSubscriptionsCreated(const NETLIBHTTPREQUEST *response); + void OnStatusChanged(const NETLIBHTTPREQUEST *response); + // profile void UpdateProfileFirstName(JSONNODE *root, MCONTACT hContact = NULL); void UpdateProfileLastName(JSONNODE *root, MCONTACT hContact = NULL); @@ -200,7 +201,7 @@ private: int OnSendMessage(MCONTACT hContact, int flags, const char *message); void OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg); - int __cdecl OnPreCreateMessage(WPARAM, LPARAM lParam); + int OnPreCreateMessage(WPARAM, LPARAM lParam); void OnGetServerHistory(const NETLIBHTTPREQUEST *response); @@ -208,18 +209,20 @@ private: MCONTACT GetChat(const char *skypename); MCONTACT AddChatRoom(const char *chatname); void SetChatStatus(MCONTACT hContact, int iStatus); + //polling - void __cdecl ParsePollData(JSONNODE *data); - void __cdecl PollingThread(void*); + void ParsePollData(JSONNODE *data); + void PollingThread(void*); void ProcessEndpointPresenceRes(JSONNODE *node); void ProcessUserPresenceRes(JSONNODE *node); void ProcessNewMessageRes(JSONNODE *node); void ProcessConversationUpdateRes(JSONNODE *node); void ProcessThreadUpdateRes(JSONNODE *node); + // utils bool IsOnline(); MEVENT AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob); - time_t __stdcall IsoToUnixTime(const TCHAR *stamp); + time_t IsoToUnixTime(const TCHAR *stamp); char *GetStringChunk(const char *haystack, size_t len, const char *start, const char *end); bool IsMe(const char *skypeName); int SkypeToMirandaStatus(const char *status); @@ -232,6 +235,7 @@ private: char *ContactUrlToName(const char *url); char *SelfUrlToName(const char *url); char *GetServerFromUrl(const char *url); + template static INT_PTR __cdecl GlobalService(WPARAM wParam, LPARAM lParam) { diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index d86b745480..d7e119874c 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -17,7 +17,7 @@ MEVENT CSkypeProto::AddEventToDb(MCONTACT hContact, WORD type, DWORD timestamp, return db_event_add(hContact, &dbei); } -time_t __stdcall CSkypeProto::IsoToUnixTime(const TCHAR *stamp) +time_t CSkypeProto::IsoToUnixTime(const TCHAR *stamp) { TCHAR date[9]; int i, y; -- cgit v1.2.3