summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Lantsev <aunsane@gmail.com>2014-04-03 12:29:38 +0000
committerAlexander Lantsev <aunsane@gmail.com>2014-04-03 12:29:38 +0000
commitcbf3dd8f411c1336c7bde2b6bbd0eb74941ac60b (patch)
tree37f5bca463411658f136952345661db54adaa4a5
parenta5b7f6edac87d6caedb83e0fa34a3dacda28a175 (diff)
Steam: authorization, login, contact list retrieving
git-svn-id: http://svn.miranda-ng.org/main/trunk@8839 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
-rw-r--r--protocols/Steam/Steam_10.vcxproj16
-rw-r--r--protocols/Steam/Steam_10.vcxproj.filters39
-rw-r--r--protocols/Steam/src/Steam/authorization.h123
-rw-r--r--protocols/Steam/src/Steam/crypto.h123
-rw-r--r--protocols/Steam/src/Steam/friend.h85
-rw-r--r--protocols/Steam/src/Steam/friend_list.h57
-rw-r--r--protocols/Steam/src/Steam/login.h62
-rw-r--r--protocols/Steam/src/Steam/steam.h37
-rw-r--r--protocols/Steam/src/common.h36
-rw-r--r--protocols/Steam/src/http_request.h20
-rw-r--r--protocols/Steam/src/stdafx.cpp55
-rw-r--r--protocols/Steam/src/steam_account.cpp90
-rw-r--r--protocols/Steam/src/steam_contacts.cpp550
-rw-r--r--protocols/Steam/src/steam_dialogs.cpp16
-rw-r--r--protocols/Steam/src/steam_events.cpp2
-rw-r--r--protocols/Steam/src/steam_instances.cpp45
-rw-r--r--protocols/Steam/src/steam_proto.cpp190
-rw-r--r--protocols/Steam/src/steam_proto.h45
-rw-r--r--protocols/Steam/src/steam_thread.cpp20
19 files changed, 1402 insertions, 209 deletions
diff --git a/protocols/Steam/Steam_10.vcxproj b/protocols/Steam/Steam_10.vcxproj
index b83444ad7a..bfb6cb08df 100644
--- a/protocols/Steam/Steam_10.vcxproj
+++ b/protocols/Steam/Steam_10.vcxproj
@@ -84,7 +84,7 @@
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<ObjectFileName>$(IntDir)\%(RelativeDir)\</ObjectFileName>
- <PrecompiledHeaderFile>steam.h</PrecompiledHeaderFile>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Link>
@@ -189,20 +189,28 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="src\http_request.h" />
- <ClInclude Include="src\steam.h" />
+ <ClInclude Include="src\common.h" />
+ <ClInclude Include="src\Steam\authorization.h" />
+ <ClInclude Include="src\Steam\crypto.h" />
+ <ClInclude Include="src\Steam\friend.h" />
+ <ClInclude Include="src\Steam\friend_list.h" />
+ <ClInclude Include="src\Steam\login.h" />
+ <ClInclude Include="src\Steam\steam.h" />
<ClInclude Include="src\steam_proto.h" />
<ClInclude Include="src\version.h" />
<ClInclude Include="src\resource.h" />
</ItemGroup>
<ItemGroup>
- <ClCompile Include="src\steam.cpp" />
- <ClCompile Include="src\steam_accounts.cpp" />
+ <ClCompile Include="src\steam_account.cpp" />
+ <ClCompile Include="src\steam_instances.cpp" />
+ <ClCompile Include="src\steam_contacts.cpp" />
<ClCompile Include="src\steam_events.cpp" />
<ClCompile Include="src\steam_dialogs.cpp" />
<ClCompile Include="src\steam_proto.cpp" />
<ClCompile Include="src\stdafx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
+ <ClCompile Include="src\steam_thread.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\Version.rc" />
diff --git a/protocols/Steam/Steam_10.vcxproj.filters b/protocols/Steam/Steam_10.vcxproj.filters
index 9dd3117f32..61152ad02f 100644
--- a/protocols/Steam/Steam_10.vcxproj.filters
+++ b/protocols/Steam/Steam_10.vcxproj.filters
@@ -13,6 +13,9 @@
<Filter Include="Resource Files\Icon">
<UniqueIdentifier>{4df49e9a-8abc-4fcc-978b-8a6e6f86d70f}</UniqueIdentifier>
</Filter>
+ <Filter Include="Header Files\Steam">
+ <UniqueIdentifier>{f3fc3bb2-b1ba-4066-bd18-d2e458cd5724}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\stdafx.cpp">
@@ -21,16 +24,22 @@
<ClCompile Include="src\steam_proto.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\steam.cpp">
+ <ClCompile Include="src\steam_events.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\steam_accounts.cpp">
+ <ClCompile Include="src\steam_dialogs.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\steam_events.cpp">
+ <ClCompile Include="src\steam_contacts.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="src\steam_dialogs.cpp">
+ <ClCompile Include="src\steam_instances.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\steam_account.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="src\steam_thread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -44,12 +53,30 @@
<ClInclude Include="src\steam_proto.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="src\steam.h">
+ <ClInclude Include="src\http_request.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="src\http_request.h">
+ <ClInclude Include="src\Steam\steam.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
+ <ClInclude Include="src\common.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="src\Steam\authorization.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Steam\friend_list.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Steam\friend.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Steam\crypto.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
+ <ClInclude Include="src\Steam\login.h">
+ <Filter>Header Files\Steam</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\resource.rc">
diff --git a/protocols/Steam/src/Steam/authorization.h b/protocols/Steam/src/Steam/authorization.h
new file mode 100644
index 0000000000..376781ba94
--- /dev/null
+++ b/protocols/Steam/src/Steam/authorization.h
@@ -0,0 +1,123 @@
+#ifndef _STEAM_AUTHORIZATION_H_
+#define _STEAM_AUTHORIZATION_H_
+
+namespace SteamWebApi
+{
+ class AuthorizationApi : public BaseApi
+ {
+ public:
+
+ class Authorization : public Result
+ {
+ friend AuthorizationApi;
+
+ private:
+ std::string steamid;
+ std::string token;
+
+ std::string emailauth;
+ std::string emailsteamid;
+
+ bool emailauth_needed;
+
+ public:
+ bool IsEmailAuthNeeded() { return emailauth_needed; }
+ const char *GetSteamid() { return steamid.c_str(); }
+ const char *GetToken() { return token.c_str(); }
+ const char *GetAuthId() { return emailauth.c_str(); }
+ const char *GetAuthCode() { return emailsteamid.c_str(); }
+
+ void SetAuthCode(char *code)
+ {
+ emailauth = code;
+ }
+ };
+
+ static void Authorize(HANDLE hConnection, const wchar_t *username, const char *password, Authorization *auth)
+ {
+ auth->success = false;
+
+ ptrA base64Username(mir_urlEncode(ptrA(mir_utf8encodeW(username))));
+
+ CryptoApi::RsaKey rsaKey;
+ CryptoApi::GetRsaKey(hConnection, base64Username, &rsaKey);
+ if (!rsaKey.IsSuccess()) return;
+
+ int size = rsaKey.GetEncryptedSize();
+ BYTE *rsaEncryptedPassword = (BYTE*)mir_alloc(size);
+ rsaKey.Encrypt((unsigned char*)password, strlen(password), rsaEncryptedPassword);
+ ptrA base64RsaEncryptedPassword(mir_base64_encode(rsaEncryptedPassword, size));
+ mir_free(rsaEncryptedPassword);
+
+ CMStringA data;
+ data.AppendFormat("username=%s", base64Username);
+ data.AppendFormat("&password=%s", ptrA(mir_urlEncode(base64RsaEncryptedPassword)));
+ data.AppendFormat("&emailauth=%s", ptrA(mir_urlEncode(auth->emailauth.c_str())));
+ data.AppendFormat("&emailsteamid=%s", auth->emailsteamid.c_str());
+ //data.AppendFormat("&captchagid=%s", result->captchagid);
+ //data.AppendFormat("&captcha_text=%s", ptrA(mir_urlEncode(result->captcha_text)));
+ data.Append("&captchagid=-1");
+ data.AppendFormat("&rsatimestamp=%llu", rsaKey.GetTimestamp());
+ data.AppendFormat("&oauth_scope=%s", "read_profile%20write_profile%20read_client%20write_client");
+ data.Append("&oauth_client_id=3638BFB1");
+
+ HttpRequest request(hConnection, REQUEST_POST, "https://steamcommunity.com/mobilelogin/dologin");
+ request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ request.SetData(data.GetBuffer(), data.GetLength());
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
+ if (!response || response->resultCode != HTTP_STATUS_OK)
+ return;
+
+ JSONNODE *root = json_parse(response->pData), *node;
+
+ node = json_get(root, "success");
+ auth->success = json_as_bool(node) > 0;
+ if (!auth->success)
+ {
+ node = json_get(root, "emailauth_needed");
+ auth->emailauth_needed = json_as_bool(node) > 0;
+ if (auth->emailauth_needed)
+ {
+ node = json_get(root, "emailsteamid");
+ auth->emailsteamid = ptrA(mir_u2a(json_as_string(node)));
+ auth->emailauth_needed = false;
+
+ /*node = json_get(root, "emaildomain");
+ result->emaildomain = json_as_string(node);*/
+ }
+
+ /*node = json_get(root, "captcha_needed");
+ result->captcha_needed = json_as_bool(node) > 0;
+ if (result->captcha_needed)
+ {
+ node = json_get(root, "captcha_gid");
+ result->captchagid = json_as_string(node);
+ }*/
+ }
+ else
+ {
+ node = json_get(root, "login_complete");
+ if (!json_as_bool(node))
+ return;
+
+ node = json_get(root, "oauth");
+ CMStringA oauth = mir_u2a(json_as_string(node));
+ oauth.Replace("\\\"", "\"");
+ root = json_parse(oauth.GetBuffer());
+ //root = json_as_node(node);
+
+ node = json_get(root, "steamid");
+ auth->steamid = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "oauth_token");
+ auth->token = ptrA(mir_u2a(json_as_string(node)));
+
+ auth->success = true;
+ }
+ }
+ };
+}
+
+
+#endif //_STEAM_AUTHORIZATION_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/crypto.h b/protocols/Steam/src/Steam/crypto.h
new file mode 100644
index 0000000000..91a8af7ba0
--- /dev/null
+++ b/protocols/Steam/src/Steam/crypto.h
@@ -0,0 +1,123 @@
+#ifndef _STEAM_CRYPTO_H_
+#define _STEAM_CRYPTO_H_
+
+ #include <openssl/rsa.h>
+ #include <openssl/bio.h>
+ #include <openssl/bn.h>
+ #include <openssl/err.h>
+ #include <openssl/evp.h>
+ #include <openssl/rand.h>
+ #include <openssl/engine.h>
+
+namespace SteamWebApi
+{
+ class CryptoApi : public BaseApi
+ {
+ public:
+
+ class RsaKey : public Result
+ {
+ friend CryptoApi;
+
+ private:
+ std::string modulus;
+ std::string exponent;
+ time_t timestamp;
+
+ public:
+ RsaKey() : timestamp(0) { }
+
+ const char * GetModulus() const
+ {
+ return modulus.c_str();
+ }
+
+ const char * GetExponent() const
+ {
+ return exponent.c_str();
+ }
+
+ time_t GetTimestamp() const
+ {
+ return timestamp;
+ }
+
+ int GetEncryptedSize() const
+ {
+ BIGNUM *n = BN_new();
+ if (!BN_hex2bn(&n, modulus.c_str()))
+ return NULL;
+
+ BIGNUM *e = BN_new();
+ if (!BN_hex2bn(&e, exponent.c_str()))
+ return NULL;
+
+ RSA *rsa = RSA_new();
+ rsa->n = n;
+ rsa->e = e;
+
+ int size = RSA_size(rsa);
+
+ RSA_free(rsa);
+
+ return size;
+ }
+
+ int Encrypt(BYTE *data, int dataSize, BYTE *encrypted) const
+ {
+ BIGNUM *n = BN_new();
+ if (!BN_hex2bn(&n, modulus.c_str()))
+ return NULL;
+
+ BIGNUM *e = BN_new();
+ if (!BN_hex2bn(&e, exponent.c_str()))
+ return NULL;
+
+ RSA *rsa = RSA_new();
+ rsa->n = n;
+ rsa->e = e;
+
+ if (RSA_public_encrypt(dataSize, data, encrypted, rsa, RSA_PKCS1_PADDING) < 0)
+ {
+ RSA_free(rsa);
+ return 1;
+ }
+
+ RSA_free(rsa);
+ return 0;
+ }
+ };
+
+ static void GetRsaKey(HANDLE hConnection, const char *username, RsaKey *rsaKey)
+ {
+ rsaKey->success = false;
+
+ HttpRequest request(hConnection, REQUEST_GET, "https://steamcommunity.com/mobilelogin/getrsakey");
+ request.AddParameter("username", username);
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
+ if (!response || response->resultCode != HTTP_STATUS_OK)
+ return;
+
+ JSONNODE *root = json_parse(response->pData), *node;
+ if (!root) return;
+
+ node = json_get(root, "success");
+ if (!json_as_bool(node)) return;
+
+ node = json_get(root, "publickey_mod");
+ rsaKey->modulus = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "publickey_exp");
+ rsaKey->exponent = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "timestamp");
+ rsaKey->timestamp = _atoi64(ptrA(mir_u2a(json_as_string(node))));
+
+ rsaKey->success = true;
+ }
+ };
+}
+
+
+#endif //_STEAM_CRYPTO_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/friend.h b/protocols/Steam/src/Steam/friend.h
new file mode 100644
index 0000000000..c6ec704b84
--- /dev/null
+++ b/protocols/Steam/src/Steam/friend.h
@@ -0,0 +1,85 @@
+#ifndef _STEAM_FRIEND_H_
+#define _STEAM_FRIEND_H_
+
+namespace SteamWebApi
+{
+ class FriendApi : public BaseApi
+ {
+ public:
+ struct Friend : public Result
+ {
+ friend FriendApi;
+ //LIST<char> friendIds;
+
+ private:
+ std::string steamId;
+
+ CMStringW nick;
+ std::string homepage;
+ std::string avatarUrl;
+
+ DWORD lastEvent;
+
+ public:
+ const char *GetSteamId() const { return steamId.c_str(); }
+ const wchar_t *GetNick() const { return nick.c_str(); }
+ const char *GetHomepage() const { return homepage.c_str(); }
+ const char *GetAvatarUrl() const { return avatarUrl.c_str(); }
+ const DWORD GetLastEvent() const { return lastEvent; }
+ };
+
+ static void LoadSummaries(HANDLE hConnection, const char *token, const char *steamId, Friend *result)
+ {
+ result->success = false;
+
+ HttpRequest *request = new HttpRequest(hConnection, REQUEST_GET, STEAM_API_URL "/ISteamUserOAuth/GetUserSummaries/v0001");
+ request->AddParameter("access_token", token);
+ request->AddParameter("steamids", steamId);
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request->Send());
+ delete request;
+
+ if (!response || response->resultCode != HTTP_STATUS_OK)
+ return;
+
+ JSONNODE *root = json_parse(response->pData), *node, *child;
+
+ /*node = json_get(root, "response");
+ root = json_as_node(node);*/
+ node = json_get(root, "players");
+ root = json_as_array(node);
+ if (root != NULL)
+ {
+ for (int i = 0;; i++)
+ {
+ child = json_at(root, i);
+ if (child == NULL)
+ break;
+
+ node = json_get(child, "steamid");
+ ptrA cSteamId(ptrA(mir_u2a(json_as_string(node))));
+ if (lstrcmpA(steamId, cSteamId))
+ return;
+ result->steamId = steamId;
+
+ node = json_get(child, "personaname");
+ result->nick = json_as_string(node);
+
+ node = json_get(child, "profileurl");
+ result->homepage = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(child, "lastlogoff");
+ //LastEventDateTS
+ result->lastEvent = json_as_int(node);
+
+ node = json_get(child, "avatarfull");
+ result->avatarUrl = ptrA(mir_u2a(json_as_string(node)));
+ }
+ }
+
+ result->success = true;
+ }
+ };
+}
+
+#endif //_STEAM_FRIEND_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/friend_list.h b/protocols/Steam/src/Steam/friend_list.h
new file mode 100644
index 0000000000..6b0a5adf50
--- /dev/null
+++ b/protocols/Steam/src/Steam/friend_list.h
@@ -0,0 +1,57 @@
+#ifndef _STEAM_FRIEND_LIST_H_
+#define _STEAM_FRIEND_LIST_H_
+
+namespace SteamWebApi
+{
+ class FriendListApi : public BaseApi
+ {
+ public:
+ class FriendList : public Result
+ {
+ friend FriendListApi;
+
+ private:
+ std::vector<std::string> friendIds;
+
+ public:
+ int GetCount() const { return friendIds.size(); }
+
+ const char * operator[](int idx) const { return friendIds[idx].c_str(); }
+ };
+
+ static void Load(HANDLE hConnection, const char *token, const char *steamId, FriendList *friendList)
+ {
+ friendList->success = false;
+
+ HttpRequest request(hConnection, REQUEST_GET, STEAM_API_URL "/ISteamUserOAuth/GetFriendList/v0001");
+ request.AddParameter("access_token", token);
+ request.AddParameter("steamid", steamId);
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
+ if (!response || response->resultCode != HTTP_STATUS_OK)
+ return;
+
+ JSONNODE *root = json_parse(response->pData), *node, *child;
+
+ node = json_get(root, "friends");
+ root = json_as_array(node);
+ if (root != NULL)
+ {
+ for (int i = 0;; i++)
+ {
+ child = json_at(root, i);
+ if (child == NULL)
+ break;
+
+ node = json_get(child, "steamid");
+ friendList->friendIds
+ .push_back((char*)ptrA(mir_u2a(json_as_string(node))));
+ }
+ }
+
+ friendList->success = true;
+ }
+ };
+}
+
+#endif //_STEAM_FRIEND_LIST_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/login.h b/protocols/Steam/src/Steam/login.h
new file mode 100644
index 0000000000..e12d942f7b
--- /dev/null
+++ b/protocols/Steam/src/Steam/login.h
@@ -0,0 +1,62 @@
+#ifndef _STEAM_LOGIN_H_
+#define _STEAM_LOGIN_H_
+
+namespace SteamWebApi
+{
+ class LogInApi : public BaseApi
+ {
+ public:
+ class LogIn : public Result
+ {
+ friend LogInApi;
+
+ private:
+ std::string steamid;
+ std::string umqid;
+ std::string message;
+
+ public:
+
+ const char *GetSteamId() { return steamid.c_str(); }
+ const char *GetSessionId() { return umqid.c_str(); }
+ const char *GetMessageId() { return message.c_str(); }
+ };
+
+ static void LogOn(HANDLE hConnection, const char *token, LogIn *login)
+ {
+ login->success = false;
+
+ CMStringA data;
+ data.AppendFormat("access_token=%s", token);
+
+ HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Logon/v0001");
+ request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ request.SetData(data.GetBuffer(), data.GetLength());
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
+ if (!response || response->resultCode != HTTP_STATUS_OK)
+ return;
+
+ JSONNODE *root = json_parse(response->pData), *node;
+
+ node = json_get(root, "error");
+ ptrW error(json_as_string(node));
+ if (lstrcmpi(error, L"OK"))
+ return;
+
+ node = json_get(root, "steamid");
+ login->steamid = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "umqid");
+ login->umqid = ptrA(mir_u2a(json_as_string(node)));
+
+ node = json_get(root, "message");
+ login->message = ptrA(mir_u2a(json_as_string(node)));
+
+ login->success = true;
+ }
+ };
+}
+
+
+#endif //_STEAM_LOGIN_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h
new file mode 100644
index 0000000000..ac995f8314
--- /dev/null
+++ b/protocols/Steam/src/Steam/steam.h
@@ -0,0 +1,37 @@
+#ifndef _STEAM_H_
+#define _STEAM_H_
+
+namespace SteamWebApi
+{
+ #define STEAM_API_URL "https://api.steampowered.com"
+
+ struct Result
+ {
+ bool success;
+ };
+
+ class BaseApi
+ {
+ public:
+ class Result
+ {
+ protected:
+ bool success;
+
+ public:
+ Result() : success(false) { }
+ bool IsSuccess() const { return success; }
+ };
+ };
+}
+
+#include <vector>
+#include <string>
+
+#include "Steam\crypto.h"
+#include "Steam\authorization.h"
+#include "Steam\login.h"
+#include "Steam\friend_list.h"
+#include "Steam\friend.h"
+
+#endif //_STEAM_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/common.h b/protocols/Steam/src/common.h
new file mode 100644
index 0000000000..9a106b3a47
--- /dev/null
+++ b/protocols/Steam/src/common.h
@@ -0,0 +1,36 @@
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <windows.h>
+
+#include <newpluginapi.h>
+#include <m_database.h>
+#include <m_langpack.h>
+#include <m_message.h>
+#include <m_netlib.h>
+#include <m_options.h>
+#include <m_popup.h>
+#include <m_json.h>
+#include <m_string.h>
+#include <m_freeimage.h>
+#include <m_protocols.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_protoint.h>
+#include <win2k.h>
+
+#include "resource.h"
+#include "version.h"
+
+#define MODULE "Steam"
+
+class CSteamProto;
+extern HINSTANCE g_hInstance;
+
+#include "http_request.h"
+
+#include "Steam\steam.h"
+
+#include "steam_proto.h"
+
+#endif //_COMMON_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h
index 6d142bdc73..3d433009e8 100644
--- a/protocols/Steam/src/http_request.h
+++ b/protocols/Steam/src/http_request.h
@@ -1,7 +1,7 @@
#ifndef _HTTP_REQUEST_H_
#define _HTTP_REQUEST_H_
-#include "steam.h"
+#include "common.h"
enum HTTP_STATUS
{
@@ -127,13 +127,21 @@ public:
m_szUrl.AppendFormat("&%s=%s", szName, szValue);
}
- /*void AddParameter(LPCSTR szName, int value)
+ void AddParameter(LPCSTR szName, int value)
{
if (m_szUrl.Find('?') == -1)
m_szUrl.AppendFormat("?%s=%i", szName, value);
else
m_szUrl.AppendFormat("&%s=%i", szName, value);
- }*/
+ }
+
+ void AddParameter(LPCSTR szName, UINT64 value)
+ {
+ if (m_szUrl.Find('?') == -1)
+ m_szUrl.AppendFormat("?%s=%llu", szName, value);
+ else
+ m_szUrl.AppendFormat("&%s=%llu", szName, value);
+ }
NETLIBHTTPREQUEST *Send()
{
@@ -148,4 +156,10 @@ private:
HANDLE m_hNetlibUser;
};
+/*class HttpPostRequest : public HttpRequest
+{
+public:
+ HttpPostRequest(HANDLE hNetlibUser, LPCSTR url) : HttpRequest(hNetlibUser, REQUEST_POST, url) { }
+};*/
+
#endif //_HTTP_REQUEST_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/stdafx.cpp b/protocols/Steam/src/stdafx.cpp
index 72b5c6b7b0..d3d389fe4d 100644
--- a/protocols/Steam/src/stdafx.cpp
+++ b/protocols/Steam/src/stdafx.cpp
@@ -1 +1,54 @@
-#include "steam.h"
+#include "common.h"
+
+int hLangpack;
+HINSTANCE g_hInstance;
+
+PLUGININFOEX pluginInfo =
+{
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM),
+ __DESCRIPTION,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ // {68F5A030-BA32-48EC-9507-5C2FBDEA5217}
+ { 0x68f5a030, 0xba32, 0x48ec, { 0x95, 0x7, 0x5c, 0x2f, 0xbd, 0xea, 0x52, 0x17 }}
+};
+
+DWORD WINAPI DllMain(HINSTANCE hInstance, DWORD, LPVOID)
+{
+ g_hInstance = hInstance;
+
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST};
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP(&pluginInfo);
+
+ PROTOCOLDESCRIPTOR pd = { sizeof(pd) };
+ pd.szName = "STEAM";
+ pd.type = PROTOTYPE_PROTOCOL;
+ pd.fnInit = (pfnInitProto)CSteamProto::InitProtoInstance;
+ pd.fnUninit = (pfnUninitProto)CSteamProto::UninitProtoInstance;
+ CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ CSteamProto::UninitProtoInstances();
+
+ return 0;
+} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp
new file mode 100644
index 0000000000..632969ad67
--- /dev/null
+++ b/protocols/Steam/src/steam_account.cpp
@@ -0,0 +1,90 @@
+#include "common.h"
+
+void CSteamProto::LogInThread(void* param)
+{
+ CMStringA token(getStringA("TokenSecret"));
+ if (token.IsEmpty())
+ {
+ ptrW username(getWStringA("Username"));
+ ptrA password(getStringA("Password"));
+
+ SteamWebApi::AuthorizationApi::Authorization authResult;
+ SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, password, &authResult);
+
+ if (authResult.IsEmailAuthNeeded()/* || authResult.captcha_needed*/)
+ {
+ do
+ {
+ if (authResult.IsEmailAuthNeeded())
+ {
+ GuardParam guard;
+
+ //lstrcpy(guard.emailDomain, authResult.emaildomain);
+
+ if (DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_GUARD),
+ NULL,
+ CSteamProto::GuardProc,
+ (LPARAM)&guard) != 1)
+ break;
+
+ authResult.SetAuthCode(guard.code);
+ }
+
+ //if (result->captcha_needed)
+ // ;// proto->fail
+
+ SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, password, &authResult);
+
+ } while (authResult.IsEmailAuthNeeded()/* || auth->captcha_needed*/);
+ }
+
+ if (!authResult.IsSuccess())
+ {
+ m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, ID_STATUS_OFFLINE);
+ return;
+ }
+
+ token = authResult.GetToken();
+ setString("TokenSecret", token);
+ setString("SteamID", authResult.GetSteamid());
+ }
+
+ SteamWebApi::LogInApi::LogIn login;
+ SteamWebApi::LogInApi::LogOn(m_hNetlibUser, token, &login);
+
+ if (!login.IsSuccess())
+ {
+ m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, ID_STATUS_OFFLINE);
+ return;
+ }
+
+ setString("SessionID", login.GetSessionId());
+ setString("MessageID", login.GetMessageId());
+
+ m_iStatus = m_iDesiredStatus;
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iDesiredStatus);
+
+ if (m_hPollingThread == NULL)
+ m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, NULL, NULL);
+
+ SteamWebApi::FriendListApi::FriendList friendList;
+ SteamWebApi::FriendListApi::Load(m_hNetlibUser, token, login.GetSteamId(), &friendList);
+
+ if (friendList.IsSuccess())
+ {
+ for (int i = 0; i < friendList.GetCount(); i++)
+ {
+ if (!FindContact(friendList[i]))
+ {
+ SteamWebApi::FriendApi::Friend rFriend;
+ SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, friendList[i], &rFriend);
+ if (!rFriend.IsSuccess()) continue;
+ AddContact(rFriend);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp
new file mode 100644
index 0000000000..83731165c9
--- /dev/null
+++ b/protocols/Steam/src/steam_contacts.cpp
@@ -0,0 +1,550 @@
+#include "common.h"
+
+MCONTACT CSteamProto::FindContact(const char *steamId)
+{
+ MCONTACT hContact = NULL;
+
+ EnterCriticalSection(&this->contact_search_lock);
+
+ for (hContact = db_find_first(this->m_szModuleName); hContact; hContact = db_find_next(hContact, this->m_szModuleName))
+ {
+ ptrA cSteamId(db_get_sa(hContact, this->m_szModuleName, "SteamID"));
+ if (!lstrcmpA(cSteamId, steamId))
+ break;
+ }
+
+ LeaveCriticalSection(&this->contact_search_lock);
+
+ return hContact;
+}
+
+MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Friend &contact)
+{
+ MCONTACT hContact = this->FindContact(contact.GetSteamId());
+ if (!hContact)
+ {
+ hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
+ CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)this->m_szModuleName);
+
+ this->setString(hContact, "SteamID", contact.GetSteamId());
+ this->setWString(hContact, "Nick", contact.GetNick());
+ this->setString(hContact, "Homepage", contact.GetHomepage());
+ this->setDword(hContact, "LastEventDateTS", contact.GetLastEvent());
+
+ /*DBVARIANT dbv;
+ if ( !this->getTString(SKYPE_SETTINGS_DEF_GROUP, &dbv))
+ {
+ ::db_set_ts(hContact, "CList", "Group", dbv.ptszVal);
+ ::db_free(&dbv);
+ }*/
+ }
+
+ return hContact;
+}
+
+//void CSteamProto::OnContactListLoadedAsync(Steam::FriendList::Result *friendList)
+//{
+// if (friendList->success)
+// {
+// for (int i = 0; i < friendList->friendIds.getCount(); i++)
+// {
+// if (!FindContact(friendList->friendIds[i]))
+// {
+// Steam::Friend::Result rFriend;
+// Steam::Friend(m_hNetlibUser)
+// .LoadSummaries(friendList->friendIds[i], &rFriend);
+// if (!rFriend.success) continue;
+// AddContact(rFriend);
+// }
+// }
+// }
+//}
+
+//void CSkypeProto::UpdateContactAuthState(MCONTACT hContact, const ContactRef &contact)
+//{
+// uint newTS = 0;
+// contact->GetPropAuthreqTimestamp(newTS);
+// DWORD oldTS = this->getDword("AuthTS", 0);
+// if (newTS > oldTS)
+// {
+// bool result;
+// if (contact->HasAuthorizedMe(result) && !result)
+// this->setByte(hContact, "Auth", !result);
+// else
+// {
+// this->delSetting(hContact, "Auth");
+// if (contact->IsMemberOfHardwiredGroup(CContactGroup::ALL_BUDDIES, result) && !result)
+// this->setByte(hContact, "Grant", !result);
+// else
+// this->delSetting(hContact, "Grant");
+// }
+//
+// this->setDword(hContact, "AuthTS", newTS);
+// }
+//}
+//
+//void CSkypeProto::UpdateContactStatus(MCONTACT hContact, const ContactRef &contact)
+//{
+// Contact::AVAILABILITY availability;
+// contact->GetPropAvailability(availability);
+// this->setWord(hContact, SKYPE_SETTINGS_STATUS, CSkypeProto::SkypeToMirandaStatus(availability));
+//
+// if (availability == Contact::SKYPEOUT)
+// this->setWord(hContact, SKYPE_SETTINGS_STATUS, ID_STATUS_ONTHEPHONE);
+// else
+// {
+// if (availability == Contact::PENDINGAUTH)
+// this->setByte(hContact, "Auth", 1);
+// else
+// this->delSetting(hContact, "Auth");
+// }
+//}
+//
+//void CSkypeProto::UpdateContactClient(MCONTACT hContact, const ContactRef &contact)
+//{
+// bool isMobile = false;
+// contact->HasCapability(Contact::CAPABILITY_MOBILE_DEVICE, isMobile/*, true*/);
+//
+// this->setTString(hContact, "MirVer", isMobile ? L"SkypeMobile" : L"Skype");
+//}
+//
+//void CSkypeProto::UpdateContactOnlineSinceTime(MCONTACT hContact, const ContactRef &contact)
+//{
+// uint newTS = 0;
+// contact->GetPropLastonlineTimestamp(newTS);
+// DWORD oldTS = ::db_get_dw(hContact, this->m_szModuleName, "OnlineSinceTS", 0);
+// if (newTS > oldTS)
+// this->setDword(hContact, "OnlineSinceTS", newTS);
+//}
+//
+//void CSkypeProto::UpdateContactLastEventDate(MCONTACT hContact, const ContactRef &contact)
+//{
+// uint newTS = 0;
+// contact->GetPropLastusedTimestamp(newTS);
+// DWORD oldTS = this->getDword(hContact, "LastEventDateTS", 0);
+// if (newTS > oldTS)
+// this->setDword(hContact, "LastEventDateTS", newTS);
+//}
+//
+//void CSkypeProto::OnContactChanged(const ContactRef &contact, int prop)
+//{
+// SEString data;
+// contact->GetPropSkypename(data);
+// wchar_t *sid = ::mir_utf8decodeW(data);
+// MCONTACT hContact = this->GetContactBySid(sid);
+// ::mir_free(sid);
+//
+// SEObject *contactObj = contact.fetch();
+//
+// if (hContact)
+// {
+// switch(prop)
+// {
+// case Contact::P_AUTHREQ_TIMESTAMP:
+// {
+// uint newTS = 0;
+// contact->GetPropAuthreqTimestamp(newTS);
+// DWORD oldTS = this->getDword(hContact, "AuthTS", 0);
+// if (newTS > oldTS)
+// this->RaiseAuthRequestEvent(newTS, contact);
+// }
+// break;
+//
+// case Contact::P_AUTHREQUEST_COUNT:
+// // todo: all authrequests after first should be catch here
+// this->UpdateContactAuthState(hContact, contact);
+// break;
+//
+// case Contact::P_AVAILABILITY:
+// this->UpdateContactStatus(hContact, contact);
+// this->UpdateChatUserStatus(contact);
+// break;
+//
+// //case CContact::P_AVATAR_IMAGE:
+// case Contact::P_AVATAR_TIMESTAMP:
+// this->UpdateProfileAvatar(contactObj, hContact);
+// break;
+//
+// //case CContact::P_MOOD_TEXT:
+// case Contact::P_MOOD_TIMESTAMP:
+// this->UpdateProfileStatusMessage(contactObj, hContact);
+// break;
+//
+// case Contact::P_FULLNAME:
+// this->UpdateChatUserNick(contact);
+// break;
+//
+// case Contact::P_PROFILE_TIMESTAMP:
+// this->UpdateProfile(contactObj, hContact);
+// break;
+// }
+// }
+//}
+//
+//void CSkypeProto::OnContactListChanged(const ContactRef &contact)
+//{
+// bool result;
+//
+// contact->IsMemberOfHardwiredGroup(CContactGroup::ALL_BUDDIES, result);
+// if (result)
+// {
+// if ( !this->contactList.contains(contact))
+// {
+// CContact::Ref newContact(contact);
+// this->contactList.append(newContact);
+// newContact.fetch();
+// }
+// }
+//
+// contact->IsMemberOfHardwiredGroup(CContactGroup::CONTACTS_WAITING_MY_AUTHORIZATION, result);
+// if (result)
+// {
+// SEString data;
+//
+// uint newTS = 0;
+// contact->GetPropAuthreqTimestamp(newTS);
+//
+// this->RaiseAuthRequestEvent(newTS, contact);
+// }
+//}
+//
+//bool CSkypeProto::IsProtoContact(MCONTACT hContact)
+//{
+// return ::lstrcmpiA(::GetContactProto(hContact), this->m_szModuleName) == 0;
+//}
+//
+//MCONTACT CSkypeProto::GetContactBySid(const wchar_t *sid)
+//{
+// MCONTACT hContact = NULL;
+//
+// ::EnterCriticalSection(&this->contact_search_lock);
+//
+// for (hContact = ::db_find_first(this->m_szModuleName); hContact; hContact = ::db_find_next(hContact, this->m_szModuleName))
+// {
+// ptrW contactSid(::db_get_wsa(hContact, this->m_szModuleName, SKYPE_SETTINGS_SID));
+// if (::lstrcmpi(contactSid, sid) == 0)
+// break;
+// }
+//
+// ::LeaveCriticalSection(&this->contact_search_lock);
+//
+// return hContact;
+//}
+//
+//MCONTACT CSkypeProto::GetContactFromAuthEvent(HANDLE hEvent)
+//{
+// // db_event_getContact
+// DWORD body[3];
+// DBEVENTINFO dbei = { sizeof(DBEVENTINFO) };
+// dbei.cbBlob = sizeof(DWORD) * 2;
+// dbei.pBlob = (PBYTE)&body;
+//
+// if (::db_event_get(hEvent, &dbei))
+// return INVALID_CONTACT_ID;
+//
+// if (dbei.eventType != EVENTTYPE_AUTHREQUEST)
+// return INVALID_CONTACT_ID;
+//
+// if (strcmp(dbei.szModule, this->m_szModuleName) != 0)
+// return INVALID_CONTACT_ID;
+//
+// return ::DbGetAuthEventContact(&dbei);
+//}
+//
+//
+//void __cdecl CSkypeProto::LoadContactList(void* data)
+//{
+// this->debugLogW(L"Updating contacts list");
+//
+// bool isFirstLoad = data != NULL;
+//
+// this->GetHardwiredContactGroup(CContactGroup::ALL_BUDDIES, this->commonList);
+// this->commonList.fetch();
+//
+// this->commonList->GetContacts(this->contactList);
+// fetch(this->contactList);
+// for (uint i = 0; i < this->contactList.size(); i++)
+// {
+// CContact::Ref contact = this->contactList[i];
+//
+// MCONTACT hContact = this->AddContact(contact);
+//
+// if ( !isFirstLoad)
+// {
+// // todo: move to AddContact?
+// this->UpdateContactAuthState(hContact, contact);
+// this->UpdateContactStatus(hContact, contact);
+//
+// ptrW nick( ::db_get_wsa(hContact, "CList", "MyHandle"));
+// if ( !nick || !::wcslen(nick))
+// {
+// nick = ::mir_utf8decodeW(contact->GetNick());
+// ::db_set_ws(hContact, "CList", "MyHandle", nick);
+// }
+//
+// this->UpdateProfile(contact.fetch(), hContact);
+// }
+// }
+//}
+//
+//void __cdecl CSkypeProto::LoadAuthWaitList(void*)
+//{
+// CContact::Refs authContacts;
+// this->GetHardwiredContactGroup(CContactGroup::CONTACTS_WAITING_MY_AUTHORIZATION, this->authWaitList);
+// this->authWaitList.fetch();
+//
+// this->authWaitList->GetContacts(authContacts);
+// for (uint i = 0; i < authContacts.size(); i++)
+// {
+// CContact::Ref contact = authContacts[i];
+//
+// uint newTS = 0;
+// contact->GetPropAuthreqTimestamp(newTS);
+//
+// this->RaiseAuthRequestEvent(newTS, contact);
+// }
+//}
+//
+//bool CSkypeProto::IsContactOnline(MCONTACT hContact)
+//{
+// return this->getWord(hContact, SKYPE_SETTINGS_STATUS, ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE;
+//}
+//
+//void CSkypeProto::SetAllContactStatus(int status)
+//{
+// ::EnterCriticalSection(&this->contact_search_lock);
+//
+// for (MCONTACT hContact = ::db_find_first(this->m_szModuleName); hContact; hContact = ::db_find_next(hContact, this->m_szModuleName))
+// {
+// if (this->getByte(hContact, "IsSkypeOut", 0) != 0)
+// continue;
+// if (this->isChatRoom(hContact))
+// continue;
+// if (this->IsContactOnline(hContact))
+// ::db_set_w(hContact, this->m_szModuleName, SKYPE_SETTINGS_STATUS, status);
+// }
+//
+// ::LeaveCriticalSection(&this->contact_search_lock);
+//}
+//
+//void CSkypeProto::OnSearchCompleted(HANDLE hSearch)
+//{
+// this->SendBroadcast(ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hSearch, 0);
+//}
+//
+//void CSkypeProto::OnContactFinded(CContact::Ref contact, HANDLE hSearch)
+//{
+// PROTOSEARCHRESULT psr = {0};
+// psr.cbSize = sizeof(psr);
+// psr.flags = PSR_TCHAR;
+//
+// SEString data;
+// contact->GetPropSkypename(data);
+// psr.id = ::mir_utf8decodeW(data);
+// contact->GetPropDisplayname(data);
+// psr.nick = ::mir_utf8decodeW(data);
+//
+// SEString firstName, lastName;
+// contact->GetFullname(firstName, lastName);
+// psr.firstName = ::mir_utf8decodeW(firstName);
+// psr.lastName = ::mir_utf8decodeW(lastName);
+//
+// {
+// contact->GetPropEmails(data);
+// mir_ptr<wchar_t> emails( ::mir_utf8decodeW(data));
+//
+// wchar_t* main = ::wcstok(emails, L" ");
+// if (main != NULL)
+// {
+// psr.email = main;
+// }
+// }
+//
+// this->SendBroadcast(ACKTYPE_SEARCH, ACKRESULT_DATA, hSearch, (LPARAM)&psr);
+//}
+//
+//void __cdecl CSkypeProto::SearchBySidAsync(void* arg)
+//{
+// mir_ptr<wchar_t> sid((wchar_t*)arg);
+//
+// MCONTACT hContact = this->GetContactBySid(sid);
+// if (hContact)
+// {
+// this->ShowNotification(TranslateT("Contact already in your contact list"), 0, hContact);
+// this->SendBroadcast(ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)SKYPE_SEARCH_BYSID, 0);
+// return;
+// }
+//
+// CContactSearch::Ref search;
+// this->CreateIdentitySearch(::mir_u2a(sid), search);
+// search.fetch();
+// search->SetProtoInfo((HANDLE)SKYPE_SEARCH_BYSID);
+//
+// bool valid;
+// if (!search->IsValid(valid) || !valid || !search->Submit())
+// return;
+//
+// search->BlockWhileSearch();
+// search->Release();
+//}
+//
+//void __cdecl CSkypeProto::SearchByEmailAsync(void* arg)
+//{
+// mir_ptr<wchar_t> email((wchar_t *)arg);
+//
+// CContactSearch::Ref search;
+// this->CreateContactSearch(search);
+// search.fetch();
+// search->SetProtoInfo((HANDLE)SKYPE_SEARCH_BYEMAIL);
+//
+// bool valid;
+// if (!search->AddEmailTerm(::mir_u2a(email), valid) || !valid || !search->Submit())
+// return;
+//
+// search->BlockWhileSearch();
+// search->Release();
+//}
+//
+//void __cdecl CSkypeProto::SearchByNamesAsync(void* arg)
+//{
+// //todo: write me
+// PROTOSEARCHRESULT *psr = (PROTOSEARCHRESULT *)arg;
+//
+// std::string nick = ::mir_utf8encodeW(psr->nick);
+// std::string fName = ::mir_utf8encodeW(psr->firstName);
+// std::string lName = " "; lName += ::mir_utf8encodeW(psr->lastName);
+//
+// CContactSearch::Ref search;
+// this->CreateContactSearch(search);
+// search.fetch();
+// search->SetProtoInfo((HANDLE)SKYPE_SEARCH_BYNAMES);
+//
+// bool valid;
+// if (nick.length() != 0)
+// {
+// search->AddStrTerm(
+// Contact::P_FULLNAME,
+// CContactSearch::CONTAINS_WORD_PREFIXES,
+// nick.c_str(),
+// valid,
+// true);
+// }
+// if (fName.length() != 0)
+// {
+// search->AddOr();
+// search->AddStrTerm(
+// Contact::P_FULLNAME,
+// CContactSearch::CONTAINS_WORD_PREFIXES,
+// fName.c_str(),
+// valid,
+// true);
+// }
+// if (lName.length() != 0)
+// {
+// search->AddOr();
+// search->AddStrTerm(
+// Contact::P_FULLNAME,
+// CContactSearch::CONTAINS_WORD_PREFIXES,
+// lName.c_str(),
+// valid,
+// true);
+// }
+//
+// if (!search->Submit())
+// return;
+//
+// search->BlockWhileSearch();
+// search->Release();
+//}
+//
+//void CSkypeProto::OnContactsReceived(const ConversationRef &conversation, const MessageRef &message)
+//{
+// CContact::Refs contacts;
+// message->GetContacts(contacts);
+//
+// uint timestamp;
+// message->GetPropTimestamp(timestamp);
+//
+// CMessage::TYPE messageType;
+// message->GetPropType(messageType);
+//
+// SEString data;
+// message->GetPropAuthor(data);
+//
+// CContact::Ref author;
+// this->GetContact(data, author);
+//
+// MCONTACT hContact = this->AddContact(author);
+//
+// SEBinary guid;
+// message->GetPropGuid(guid);
+// ReadMessageParam param = { guid, messageType };
+//
+// PROTORECVEVENT pre = { 0 };
+// pre.flags = PREF_UTF;
+// pre.lParam = (LPARAM)&param;
+// pre.timestamp = timestamp;
+//
+// int msgSize = 1;
+// pre.szMessage = (char *)::mir_alloc(msgSize);
+// pre.szMessage[0] = 0;
+//
+// int len = 0;
+// char* pCur = &pre.szMessage[0];
+//
+// for (size_t i = 0; i < contacts.size(); i ++)
+// {
+// contacts[i]->GetIdentity(data);
+// if ( ::lstrcmpi(mir_ptr<wchar_t>(::mir_utf8decodeW(data)), this->login) != 0)
+// this->AddContact(contacts[i]);
+// }
+//
+// char *text = ::mir_utf8encode(::Translate("Contacts received"));
+//
+// this->AddDBEvent(
+// hContact,
+// SKYPE_DB_EVENT_TYPE_CONTACTS,
+// timestamp,
+// PREF_UTF,
+// (DWORD)::strlen(text) + 1,
+// (PBYTE)text);
+//}
+//
+//void CSkypeProto::OnContactsSent(const ConversationRef &conversation, const MessageRef &message)
+//{
+// SEString data;
+//
+// CMessage::TYPE messageType;
+// message->GetPropType(messageType);
+//
+// uint timestamp;
+// message->GetPropTimestamp(timestamp);
+//
+// CMessage::SENDING_STATUS status;
+// message->GetPropSendingStatus(status);
+//
+// CParticipant::Refs participants;
+// conversation->GetParticipants(participants, CConversation::OTHER_CONSUMERS);
+// participants[0]->GetPropIdentity(data);
+//
+// CContact::Ref receiver;
+// this->GetContact(data, receiver);
+//
+// MCONTACT hContact = this->AddContact(receiver);
+// this->SendBroadcast(
+// hContact,
+// ACKTYPE_CONTACTS,
+// status == CMessage::FAILED_TO_SEND ? ACKRESULT_FAILED : ACKRESULT_SUCCESS,
+// (HANDLE)message->getOID(), 0);
+//}
+//
+//void CSkypeProto::OnContactsEvent(const ConversationRef &conversation, const MessageRef &message)
+//{
+// SEString author;
+// message->GetPropAuthor(author);
+//
+// if (::wcsicmp(mir_ptr<wchar_t>(::mir_utf8decodeW(author)), this->login) == 0)
+// this->OnContactsSent(conversation, message);
+// else
+// this->OnContactsReceived(conversation, message);
+//} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_dialogs.cpp b/protocols/Steam/src/steam_dialogs.cpp
index 5c2ad45743..a0f79d3744 100644
--- a/protocols/Steam/src/steam_dialogs.cpp
+++ b/protocols/Steam/src/steam_dialogs.cpp
@@ -1,4 +1,4 @@
-#include "steam.h"
+#include "common.h"
//#include <gdiplus.h>
//#pragma comment(lib, "GdiPlus.lib")
@@ -192,8 +192,8 @@ INT_PTR CALLBACK CSteamProto::MainOptionsProc(HWND hwnd, UINT message, WPARAM wP
proto = (CSteamProto*)lParam;
SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam);
- ptrA username(proto->getStringA("Username"));
- SetDlgItemTextA(hwnd, IDC_USERNAME, username);
+ ptrW username(proto->getWStringA("Username"));
+ SetDlgItemText(hwnd, IDC_USERNAME, username);
ptrA password(proto->getStringA("Password"));
SetDlgItemTextA(hwnd, IDC_PASSWORD, password);
@@ -251,15 +251,15 @@ INT_PTR CALLBACK CSteamProto::MainOptionsProc(HWND hwnd, UINT message, WPARAM wP
case WM_NOTIFY:
if (reinterpret_cast<NMHDR*>(lParam)->code == PSN_APPLY/* && !proto->IsOnline()*/)
{
- char username[128];
- GetDlgItemTextA(hwnd, IDC_SL, username, SIZEOF(username));
- proto->setString("Username", username);
+ wchar_t username[128];
+ GetDlgItemText(hwnd, IDC_USERNAME, username, SIZEOF(username));
+ proto->setWString("Username", username);
/*mir_free(proto->login);
proto->login = ::mir_wstrdup(sid);*/
char password[128];
- GetDlgItemTextA(hwnd, IDC_PW, password, SIZEOF(password));
- db_set_s(NULL, proto->m_szModuleName, "Password", password);
+ GetDlgItemTextA(hwnd, IDC_PASSWORD, password, SIZEOF(password));
+ proto->setString("Password", password);
/*wchar_t tstr[128];
GetDlgItemText(hwnd, IDC_GROUP, tstr, SIZEOF(tstr));
diff --git a/protocols/Steam/src/steam_events.cpp b/protocols/Steam/src/steam_events.cpp
index dd78bd2acd..0099f43456 100644
--- a/protocols/Steam/src/steam_events.cpp
+++ b/protocols/Steam/src/steam_events.cpp
@@ -1,4 +1,4 @@
-#include "steam.h"
+#include "common.h"
int CSteamProto::OnModulesLoaded(WPARAM, LPARAM)
{
diff --git a/protocols/Steam/src/steam_instances.cpp b/protocols/Steam/src/steam_instances.cpp
new file mode 100644
index 0000000000..82b62f9654
--- /dev/null
+++ b/protocols/Steam/src/steam_instances.cpp
@@ -0,0 +1,45 @@
+#include "common.h"
+
+int CSteamProto::CompareProtos(const CSteamProto *p1, const CSteamProto *p2)
+{
+ return lstrcmp(p1->m_tszUserName, p2->m_tszUserName);
+}
+
+LIST<CSteamProto> CSteamProto::InstanceList(1, CSteamProto::CompareProtos);
+
+CSteamProto* CSteamProto::InitProtoInstance(const char* protoName, const wchar_t* userName)
+{
+ CSteamProto *ppro = new CSteamProto(protoName, userName);
+ InstanceList.insert(ppro);
+
+ return ppro;
+}
+
+int CSteamProto::UninitProtoInstance(CSteamProto* ppro)
+{
+ InstanceList.remove(ppro);
+ delete ppro;
+
+ return 0;
+}
+
+void CSteamProto::UninitProtoInstances()
+{
+ for (int i = InstanceList.getCount(); i > 0; i--)
+ UninitProtoInstance(InstanceList[i]);
+ InstanceList.destroy();
+}
+
+CSteamProto* CSteamProto::GetContactProtoInstance(MCONTACT hContact)
+{
+ char *proto = (char *)::CallService(MS_PROTO_GETCONTACTBASEPROTO, hContact, 0);
+
+ if (proto == NULL)
+ return NULL;
+
+ for (int i = 0; i < InstanceList.getCount(); i++)
+ if (!strcmp(proto, InstanceList[i]->m_szModuleName))
+ return InstanceList[i];
+
+ return NULL;
+} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp
index acaacde37e..ad87d64f29 100644
--- a/protocols/Steam/src/steam_proto.cpp
+++ b/protocols/Steam/src/steam_proto.cpp
@@ -1,13 +1,16 @@
-#include "steam.h"
+#include "common.h"
CSteamProto::CSteamProto(const char* protoName, const TCHAR* userName) :
PROTO<CSteamProto>(protoName, userName)
{
CreateProtoService(PS_CREATEACCMGRUI, &CSteamProto::OnAccountManagerInit);
+
+ InitializeCriticalSection(&this->contact_search_lock);
}
CSteamProto::~CSteamProto()
{
+ DeleteCriticalSection(&this->contact_search_lock);
}
MCONTACT __cdecl CSteamProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
@@ -69,9 +72,9 @@ DWORD_PTR __cdecl CSteamProto:: GetCaps(int type, MCONTACT hContact)
case PFLAGNUM_2:
return PF2_ONLINE;
case PFLAG_UNIQUEIDTEXT:
- return (DWORD_PTR)::Translate("Username");
+ return (DWORD_PTR)Translate("SteamID");
case PFLAG_UNIQUEIDSETTING:
- return (DWORD_PTR)"Username";
+ return (DWORD_PTR)"SteamID";
default:
return 0;
}
@@ -134,170 +137,6 @@ int __cdecl CSteamProto::SendUrl(MCONTACT hContact, int flags, const char *url)
int __cdecl CSteamProto::SetApparentMode(MCONTACT hContact, int mode) { return 0; }
-NETLIBHTTPREQUEST *CSteamProto::LoginRequest(const char *username, const char *password, const char *timestamp, const char *captchagid, const char *captcha_text, const char *emailauth, const char *emailsteamid)
-{
- HttpRequest request = HttpRequest(m_hNetlibUser, REQUEST_POST, "https://steamcommunity.com/login/dologin/");
- request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
- request.AddHeader("Accept-Encoding", "deflate, gzip");
-
- CMStringA param;
- param.AppendFormat("username=%s", mir_urlEncode(username));
- param.AppendFormat("&password=%s", mir_urlEncode(password));
- param.AppendFormat("&captchagid=%s", captchagid);
- param.AppendFormat("&captcha_text=%s", mir_urlEncode(captcha_text));
- param.AppendFormat("&emailauth=%s", mir_urlEncode(emailauth));
- param.AppendFormat("&emailsteamid=%s", emailsteamid);
- param.AppendFormat("&rsatimestamp=%s", timestamp);
-
- request.SetData(param.GetBuffer(), param.GetLength());
-
- return request.Send();
-}
-
-#include <openssl/rsa.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/engine.h>
-
-bool CSteamProto::Login()
-{
- ptrA username(getStringA("Username"));
-
- HttpRequest request(m_hNetlibUser, REQUEST_GET, "https://steamcommunity.com/login/getrsakey");
- request.AddParameter("username", username);
-
- mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
-
- if (!response || response->resultCode != HTTP_STATUS_OK)
- return false;
-
- JSONNODE *root = json_parse(response->pData), *node;
- if (!root)
- return false;
-
- node = json_get(root, "success");
- if (!json_as_bool(node))
- return false;
-
- node = json_get(root, "timestamp");
- ptrA timestamp = ptrA(mir_t2a(json_as_string(node)));
-
- node = json_get(root, "publickey_mod");
- const char *mod = mir_t2a(json_as_string(node));
-
- node = json_get(root, "publickey_exp");
- const char *exp = mir_t2a(json_as_string(node));
-
- const char *password = getStringA("Password");
-
- BIGNUM *modulus = BN_new();
- if (!BN_hex2bn(&modulus, mod))
- return false;
-
- BIGNUM *exponent = BN_new();
- if (!BN_hex2bn(&exponent, exp))
- return false;
-
- RSA *rsa = RSA_new();
- rsa->n = modulus;
- rsa->e = exponent;
-
- int size = RSA_size(rsa);
- BYTE *ePassword = (BYTE*)mir_calloc(size);
- if (RSA_public_encrypt((int)strlen(password), (const unsigned char*)password, ePassword, rsa, RSA_PKCS1_PADDING) < 0)
- return false;
-
- char *sPassword = mir_base64_encode(ePassword, size);
-
- bool captcha_needed, emailauth_needed;
- CMStringA captchagid("-1"), captcha_text, emailauth, emailsteamid;
- do
- {
- response = Authorize(username, sPassword, timestamp, captchagid.GetBuffer(), captcha_text.GetBuffer(), emailauth.GetBuffer(), emailsteamid.GetBuffer());
- if (!response || response->resultCode != HTTP_STATUS_OK)
- return false;
-
- root = json_parse(response->pData);
-
- node = json_get(root, "emailauth_needed");
- emailauth_needed = json_as_bool(node);
- if (emailauth_needed)
- {
- GuardParam guard;
-
- node = json_get(root, "emailsteamid");
- emailsteamid = ptrA(mir_t2a(json_as_string(node)));
-
- node = json_get(root, "emaildomain");
- strcpy(guard.domain, mir_u2a(json_as_string(node)));
-
- if (DialogBoxParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_GUARD),
- NULL,
- CSteamProto::GuardProc,
- (LPARAM)&guard) != 1)
- return false;
-
- emailauth = guard.code;
- }
-
- node = json_get(root, "captcha_needed");
- captcha_needed = json_as_bool(node);
- if (captcha_needed)
- {
- node = json_get(root, "captcha_gid");
- captchagid = ptrA(mir_t2a(json_as_string(node)));
-
- CMStringA url = CMStringA("https://steamcommunity.com/public/captcha.php?gid=") + captchagid;
- CallService(MS_UTILS_OPENURL, 0, (LPARAM)url.GetBuffer());
-
- //request = HttpRequest(m_hNetlibUser, REQUEST_GET, "https://steamcommunity.com/public/captcha.php?gid=");
- //request.AddUrlPart(gid);
-
- //response = request.Send();
-
- //if (!response || response->resultCode != HTTP_STATUS_OK)
- // return false;
-
- CaptchaParam captcha;
- captcha.size = response->dataLength;
- captcha.data = (BYTE*)mir_alloc(response->dataLength);
- memcpy(captcha.data, response->pData, captcha.size);
-
- if (DialogBoxParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_CAPTCHA),
- NULL,
- CSteamProto::CaptchaProc,
- (LPARAM)&captcha) != 1)
- return false;
-
- captcha_text = captcha.text;
- }
-
- node = json_get(root, "success");
- if (!json_as_bool(node) && !emailauth_needed && !captcha_needed)
- return false;
-
- } while (emailauth_needed || captcha_needed);
-
- node = json_get(root, "success");
- if (!json_as_bool(node))
- return false;
-
- // {"success":true, "login_complete" : true, "transfer_url" : "https:\/\/store.steampowered.com\/\/login\/transfer", "transfer_parameters" : {"steamid":"*", "token" : "*", "remember_login" : false, "webcookie" : "*"}}
-
- return true;
-}
-
-bool CSteamProto::Logout()
-{
- return true;
-}
-
int CSteamProto::SetStatus(int new_status)
{
if (new_status == m_iDesiredStatus)
@@ -308,9 +147,9 @@ int CSteamProto::SetStatus(int new_status)
if (new_status == ID_STATUS_OFFLINE)
{
- Logout();
- m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
+ m_bTerminated = true;
+ m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)old_status, m_iStatus);
if (!Miranda_Terminated())
@@ -325,9 +164,16 @@ int CSteamProto::SetStatus(int new_status)
{
if (old_status == ID_STATUS_OFFLINE/* && !this->IsOnline()*/)
{
- this->m_iStatus = ID_STATUS_CONNECTING;
- /*if (!Login())
- return 0;*/
+ UINT64 id = 76561197960435530;
+ DWORD in_db = id;
+ id = in_db;
+
+ m_iStatus = ID_STATUS_CONNECTING;
+ ForkThread(&CSteamProto::LogInThread, NULL);
+
+ //ptrA steamId(getStringA("SteamID"));
+ //Steam::FriendList(m_hNetlibUser/*, token*/)
+ // .LoadAsync(steamId, CallbackConverter<Steam::FriendList::Result, &CSteamProto::OnContactListLoadedAsync>, this);
}
else
{
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h
index 623dc4296c..3a742a66b3 100644
--- a/protocols/Steam/src/steam_proto.h
+++ b/protocols/Steam/src/steam_proto.h
@@ -1,8 +1,6 @@
#ifndef _STEAM_PROTO_H_
#define _STEAM_PROTO_H_
-#include "http_request.h"
-
struct CaptchaParam
{
BYTE *data;
@@ -12,10 +10,19 @@ struct CaptchaParam
struct GuardParam
{
- char domain[32];
+ wchar_t emailDomain[32];
char code[10];
};
+template<typename T, void (CSteamProto::*Callback)(T*)>
+void CallbackConverter(void *owner, void *arg)
+{
+ T *typedArg = (T*)arg;
+ CSteamProto *proto = (CSteamProto*)owner;
+ if (owner != NULL)
+ (proto->*Callback)(typedArg);
+}
+
class CSteamProto : public PROTO<CSteamProto>
{
public:
@@ -67,24 +74,34 @@ public:
virtual int __cdecl OnEvent( PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam );
- // accounts
- static CSteamProto* InitAccount(const char* protoName, const wchar_t* userName);
- static int UninitAccount(CSteamProto* ppro);
+ // instances
+ static CSteamProto* InitProtoInstance(const char* protoName, const wchar_t* userName);
+ static int UninitProtoInstance(CSteamProto* ppro);
- static CSteamProto* GetContactAccount(MCONTACT hContact);
- static void UninitAccounts();
+ static CSteamProto* GetContactProtoInstance(MCONTACT hContact);
+ static void UninitProtoInstances();
protected:
+ bool m_bTerminated;
+ HANDLE m_hPollingThread;
+ CRITICAL_SECTION contact_search_lock;
- NETLIBHTTPREQUEST *LoginRequest(const char *username, const char *password, const char *timestamp, const char *captchagid, const char *captcha_text, const char *emailauth, const char *emailsteamid);
-
- bool Login();
- bool Logout();
-
- // accounts
+ // instances
static LIST<CSteamProto> InstanceList;
static int CompareProtos(const CSteamProto *p1, const CSteamProto *p2);
+ // pooling thread
+ int PollStatus();
+ void __cdecl PollingThread(void*);
+
+ // account
+ void __cdecl LogInThread(void*);
+
+ // contacts
+ MCONTACT FindContact(const char *steamId);
+ MCONTACT AddContact(const SteamWebApi::FriendApi::Friend &contact);
+ //void OnContactListLoadedAsync(Steam::FriendList::Result *result);
+
//events
int OnModulesLoaded(WPARAM, LPARAM);
int OnPreShutdown(WPARAM, LPARAM);
diff --git a/protocols/Steam/src/steam_thread.cpp b/protocols/Steam/src/steam_thread.cpp
new file mode 100644
index 0000000000..04b631a41c
--- /dev/null
+++ b/protocols/Steam/src/steam_thread.cpp
@@ -0,0 +1,20 @@
+#include "common.h"
+
+int CSteamProto::PollStatus()
+{
+ Sleep(2000);
+
+ return 0;
+}
+
+void CSteamProto::PollingThread(void*)
+{
+ debugLogA("CSteamProto::PollingThread: entering");
+
+ while (!m_bTerminated)
+ if (PollStatus() == -1)
+ break;
+
+ m_hPollingThread = NULL;
+ debugLogA("CSteamProto::PollingThread: leaving");
+} \ No newline at end of file