summaryrefslogtreecommitdiff
path: root/protocols/Steam/src
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Steam/src')
-rw-r--r--protocols/Steam/src/Steam/authorization.h12
-rw-r--r--protocols/Steam/src/Steam/friend.h29
-rw-r--r--protocols/Steam/src/Steam/login.h4
-rw-r--r--protocols/Steam/src/Steam/poll.h33
-rw-r--r--protocols/Steam/src/Steam/rsa_key.h73
-rw-r--r--protocols/Steam/src/Steam/search.h78
-rw-r--r--protocols/Steam/src/Steam/steam.h8
-rw-r--r--protocols/Steam/src/common.h5
-rw-r--r--protocols/Steam/src/http_request.h14
-rw-r--r--protocols/Steam/src/steam_account.cpp222
-rw-r--r--protocols/Steam/src/steam_contacts.cpp42
-rw-r--r--protocols/Steam/src/steam_proto.cpp14
-rw-r--r--protocols/Steam/src/steam_proto.h8
-rw-r--r--protocols/Steam/src/steam_thread.cpp78
14 files changed, 525 insertions, 95 deletions
diff --git a/protocols/Steam/src/Steam/authorization.h b/protocols/Steam/src/Steam/authorization.h
index c0015cdebc..17aa3410d6 100644
--- a/protocols/Steam/src/Steam/authorization.h
+++ b/protocols/Steam/src/Steam/authorization.h
@@ -56,7 +56,7 @@ namespace SteamWebApi
}
};
- static void Authorize(HANDLE hConnection, const wchar_t *username, const char *password, AuthResult *authResult)
+ static void Authorize(HANDLE hConnection, const wchar_t *username, const char *password, const char *timestamp, AuthResult *authResult)
{
authResult->success = false;
authResult->captcha_needed = false;
@@ -64,7 +64,7 @@ namespace SteamWebApi
ptrA base64Username(mir_urlEncode(ptrA(mir_utf8encodeW(username))));
- CryptoApi::RsaKey rsaKey;
+ /*CryptoApi::RsaKey rsaKey;
CryptoApi::GetRsaKey(hConnection, base64Username, &rsaKey);
if (!rsaKey.IsSuccess()) return;
@@ -72,16 +72,16 @@ namespace SteamWebApi
BYTE *rsaEncryptedPassword = (BYTE*)mir_alloc(size);
rsaKey.Encrypt((unsigned char*)password, strlen(password), rsaEncryptedPassword);
ptrA base64RsaEncryptedPassword(mir_base64_encode(rsaEncryptedPassword, size));
- mir_free(rsaEncryptedPassword);
+ mir_free(rsaEncryptedPassword);*/
CMStringA data;
data.AppendFormat("username=%s", base64Username);
- data.AppendFormat("&password=%s", ptrA(mir_urlEncode(base64RsaEncryptedPassword)));
+ data.AppendFormat("&password=%s", ptrA(mir_urlEncode(password)));
data.AppendFormat("&emailauth=%s", ptrA(mir_urlEncode(authResult->emailauth.c_str())));
data.AppendFormat("&emailsteamid=%s", authResult->emailsteamid.c_str());
- data.AppendFormat("&captchagid=%s", authResult->captchagid);
+ data.AppendFormat("&captchagid=%s", authResult->captchagid.c_str());
data.AppendFormat("&captcha_text=%s", ptrA(mir_urlEncode(authResult->captcha_text.c_str())));
- data.AppendFormat("&rsatimestamp=%llu", rsaKey.GetTimestamp());
+ data.AppendFormat("&rsatimestamp=%s", timestamp);
data.AppendFormat("&oauth_scope=%s", "read_profile write_profile read_client write_client");
data.Append("&oauth_client_id=DE45CD61");
diff --git a/protocols/Steam/src/Steam/friend.h b/protocols/Steam/src/Steam/friend.h
index b5f544523f..2c89dd718a 100644
--- a/protocols/Steam/src/Steam/friend.h
+++ b/protocols/Steam/src/Steam/friend.h
@@ -9,25 +9,30 @@ namespace SteamWebApi
struct Friend : public Result
{
friend FriendApi;
- //LIST<char> friendIds;
private:
std::string steamId;
std::wstring nickname;
+ std::wstring realname;
+ std::string countryCode;
std::string homepage;
std::string avatarUrl;
- int status;
+ int state;
+ DWORD created;
DWORD lastEvent;
public:
const char *GetSteamId() const { return steamId.c_str(); }
const wchar_t *GetNickname() const { return nickname.c_str(); }
+ const wchar_t *GetRealname() const { return realname.c_str(); }
+ const char *GetCountryCode() const { return countryCode.c_str(); }
const char *GetHomepage() const { return homepage.c_str(); }
const char *GetAvatarUrl() const { return avatarUrl.c_str(); }
- int GetStatus() const { return status; }
+ int GetState() const { return state; }
+ const DWORD GetCreated() const { return created; }
const DWORD GetLastEvent() const { return lastEvent; }
};
@@ -47,8 +52,6 @@ namespace SteamWebApi
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)
@@ -68,20 +71,32 @@ namespace SteamWebApi
node = json_get(child, "personaname");
result->nickname = json_as_string(node);
+ node = json_get(child, "realname");
+ if (node != NULL)
+ result->realname = json_as_string(node);
+
+ node = json_get(child, "loccountrycode");
+ if (node != NULL)
+ result->countryCode = ptrA(mir_u2a(json_as_string(node)));
+
node = json_get(child, "personastate");
- result->status = json_as_int(node);
+ result->state = json_as_int(node);
node = json_get(child, "profileurl");
result->homepage = ptrA(mir_u2a(json_as_string(node)));
+ node = json_get(child, "timecreated");
+ result->created = json_as_int(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)));
}
}
+ else
+ return;
result->success = true;
}
diff --git a/protocols/Steam/src/Steam/login.h b/protocols/Steam/src/Steam/login.h
index aab7225a4d..a6f743c45c 100644
--- a/protocols/Steam/src/Steam/login.h
+++ b/protocols/Steam/src/Steam/login.h
@@ -57,10 +57,6 @@ namespace SteamWebApi
loginResult->success = true;
}
- static void Relogon(HANDLE hConnection, const char *token, LoginResult *loginResult)
- {
- }
-
static void Logoff(HANDLE hConnection, const char *token, const char *sessionId)
{
CMStringA data;
diff --git a/protocols/Steam/src/Steam/poll.h b/protocols/Steam/src/Steam/poll.h
index a8e7c76306..f5b0c602ea 100644
--- a/protocols/Steam/src/Steam/poll.h
+++ b/protocols/Steam/src/Steam/poll.h
@@ -8,12 +8,12 @@ namespace SteamWebApi
public:
enum POOL_TYPE
{
- UNKNOWN,
- MESSAGE,
- MYMESSAGE,
- TYPING,
- STATE,
- //POOL_TYPE_RELATIONSHIP = 4
+ POOL_TYPE_UNKNOWN,
+ POOL_TYPE_MESSAGE,
+ POOL_TYPE_MYMESSAGE,
+ POOL_TYPE_TYPING,
+ POOL_TYPE_STATE,
+ //POOL_TYPE_RELATIONSHIP
};
class PoolItem : public Result
@@ -26,7 +26,7 @@ namespace SteamWebApi
POOL_TYPE type;
public:
- PoolItem() : timestamp(0), type(POOL_TYPE::UNKNOWN) { }
+ PoolItem() : timestamp(0), type(POOL_TYPE_UNKNOWN) { }
const char *GetSteamId() const { return steamId.c_str(); }
const DWORD GetTimestamp() const { return timestamp; }
@@ -80,17 +80,18 @@ namespace SteamWebApi
static void PollStatus(HANDLE hConnection, const char *token, const char *sessionId, UINT32 messageId, PollResult *pollResult)
{
pollResult->success = false;
+ pollResult->need_relogin = false;
+ pollResult->items.clear();
CMStringA data;
data.AppendFormat("access_token=%s", token);
data.AppendFormat("&umqid=%s", sessionId);
- data.AppendFormat("&message=%i", messageId);
- //data.Append("&sectimeout=90");
+ data.AppendFormat("&message=%iu", messageId);
HttpRequest request(hConnection, REQUEST_POST, STEAM_API_URL "/ISteamWebUserPresenceOAuth/Poll/v0001");
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.SetData(data.GetBuffer(), data.GetLength());
- request.timeout = 90000;
+ request.timeout = 90000; // may need to encrease timeout
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
if (!response || response->resultCode != HTTP_STATUS_OK)
@@ -103,7 +104,7 @@ namespace SteamWebApi
if (!lstrcmpi(error, L"Not Logged On"))
{
pollResult->need_relogin = true;
- pollResult->success = true;
+ //pollResult->success = true;
return;
}
else
@@ -139,9 +140,9 @@ namespace SteamWebApi
Message *message = new Message();
if (_tcsstr(type, L"my_") == NULL)
- message->type = POOL_TYPE::MESSAGE;
+ message->type = POOL_TYPE_MESSAGE;
else
- message->type = POOL_TYPE::MYMESSAGE;
+ message->type = POOL_TYPE_MYMESSAGE;
node = json_get(child, "text");
if (node != NULL) message->text = json_as_string(node);
@@ -154,12 +155,12 @@ namespace SteamWebApi
else if(!lstrcmpi(type, L"typing"))
{
item = new Typing();
- item->type = POOL_TYPE::TYPING;
+ item->type = POOL_TYPE_TYPING;
}
else if (!lstrcmpi(type, L"personastate"))
{
State *state = new State();
- state->type = POOL_TYPE::STATE;
+ state->type = POOL_TYPE_STATE;
node = json_get(child, "persona_state");
if (node != NULL) state->status = json_as_int(node);
@@ -171,7 +172,7 @@ namespace SteamWebApi
}
/*else if (!lstrcmpi(type, L"personarelationship"))
{
- type = (int)POOL_TYPE::RELATIONSHIP;
+ type = POOL_TYPE_RELATIONSHIP;
}*/
/*else if (!lstrcmpi(type, L"leftconversation"))
{
diff --git a/protocols/Steam/src/Steam/rsa_key.h b/protocols/Steam/src/Steam/rsa_key.h
new file mode 100644
index 0000000000..a5322d3523
--- /dev/null
+++ b/protocols/Steam/src/Steam/rsa_key.h
@@ -0,0 +1,73 @@
+#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>
+
+//#include "../RSA/RSA.h";
+//#include "../RSA/Key.h";
+//#include "../RSA/BigInt.h";
+//
+//#include <vector>;
+
+namespace SteamWebApi
+{
+ class RsaKeyApi : public BaseApi
+ {
+ public:
+
+ class RsaKey : public Result
+ {
+ friend RsaKeyApi;
+
+ private:
+ std::string modulus;
+ std::string exponent;
+ std::string timestamp;
+
+ public:
+ const char * GetModulus() const { return modulus.c_str(); }
+ const char * GetExponent() const { return exponent.c_str(); }
+ const char * GetTimestamp() const { return timestamp.c_str(); }
+ };
+
+ static void GetRsaKey(HANDLE hConnection, const wchar_t *username, RsaKey *rsaKey)
+ {
+ rsaKey->success = false;
+
+ ptrA base64Username(mir_urlEncode(ptrA(mir_utf8encodeW(username))));
+
+ HttpRequest request(hConnection, REQUEST_GET, STEAM_COMMUNITY_URL "/mobilelogin/getrsakey");
+ request.AddParameter("username", (char*)base64Username);
+
+ 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 = 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/search.h b/protocols/Steam/src/Steam/search.h
new file mode 100644
index 0000000000..ad4bd9c5d9
--- /dev/null
+++ b/protocols/Steam/src/Steam/search.h
@@ -0,0 +1,78 @@
+#ifndef _STEAM_SEARCH_H_
+#define _STEAM_SEARCH_H_
+
+namespace SteamWebApi
+{
+ class SearchApi : public BaseApi
+ {
+ public:
+
+ class SearchItem : public Result
+ {
+ };
+
+ class SearchResult : public Result
+ {
+ friend SearchApi;
+
+ private:
+ int count;
+ std::vector<SearchItem*> items;
+
+ public:
+ SearchResult() : count(0) { }
+
+ int GetCount() { return count; }
+ };
+
+ static void Search(HANDLE hConnection, const char *token, const char *text, SearchResult *searchResult)
+ {
+ searchResult->success = false;
+ searchResult->count = 0;
+ searchResult->items.clear();
+
+ HttpRequest request(hConnection, REQUEST_GET, STEAM_API_URL "/ISteamUserOAuth/Search/v0001");
+ request.AddParameter("access_token=%s", token);
+ request.AddParameter("&keywords=%s", text);
+ request.AddParameter("&offset=0&count=50&targets=users&fields=all");
+
+ 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, "success");
+ searchResult->success = json_as_bool(node) > 0;
+ if (!searchResult->success)
+ return;
+
+ node = json_get(root, "count");
+ searchResult->count = json_as_int(node);
+
+ //node = json_get(root, "total");
+ //searchResult->total = json_as_int(node);
+
+ if (searchResult->count == 0)
+ return;
+
+ node = json_get(root, "results");
+ root = json_as_array(node);
+ if (root != NULL)
+ {
+ for (int i = 0;; i++)
+ {
+ child = json_at(root, i);
+ if (child == NULL)
+ break;
+
+ SearchItem *item = NULL;
+ }
+ }
+
+ searchResult->success = true;
+ }
+ };
+}
+
+#endif //_STEAM_SEARCH_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h
index 54acf01ab8..acdb86393d 100644
--- a/protocols/Steam/src/Steam/steam.h
+++ b/protocols/Steam/src/Steam/steam.h
@@ -3,7 +3,7 @@
namespace SteamWebApi
{
- #define STEAM_API_URL "https://api.steampowered.com:443"
+ #define STEAM_API_URL "https://api.steampowered.com"
#define STEAM_COMMUNITY_URL "https://steamcommunity.com"
struct Result
@@ -26,15 +26,13 @@ namespace SteamWebApi
};
}
-#include <vector>
-#include <string>
-
-#include "Steam\crypto.h"
+#include "Steam\rsa_key.h"
#include "Steam\authorization.h"
#include "Steam\login.h"
#include "Steam\friend_list.h"
#include "Steam\friend.h"
#include "Steam\poll.h"
#include "Steam\message.h"
+#include "Steam\search.h"
#endif //_STEAM_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/common.h b/protocols/Steam/src/common.h
index 34e155daa3..7c0a9a9abe 100644
--- a/protocols/Steam/src/common.h
+++ b/protocols/Steam/src/common.h
@@ -22,6 +22,11 @@
#include <m_protoint.h>
#include <win2k.h>
+#include <vector>
+#include <string>
+
+//#include <openssl/rsa.h>
+
#include "resource.h"
#include "version.h"
diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h
index a065fec60e..f69b524c8a 100644
--- a/protocols/Steam/src/http_request.h
+++ b/protocols/Steam/src/http_request.h
@@ -129,20 +129,28 @@ 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)
+ /*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);
+ }*/
+
+ void AddParameter(LPCSTR szValue)
+ {
+ if (m_szUrl.Find('?') == -1)
+ m_szUrl.AppendFormat("?%s", szValue);
+ else
+ m_szUrl.AppendFormat("&%s", szValue);
}
NETLIBHTTPREQUEST *Send()
diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp
index 768bfc4914..61469a02a1 100644
--- a/protocols/Steam/src/steam_account.cpp
+++ b/protocols/Steam/src/steam_account.cpp
@@ -27,8 +27,8 @@ int CSteamProto::MirandaToSteamState(int status)
{
switch (status)
{
- case ID_STATUS_ONLINE:
- return 1; //Online
+ case ID_STATUS_OFFLINE:
+ return 0; //Offline
case ID_STATUS_DND:
return 2; //Busy
case ID_STATUS_AWAY:
@@ -42,13 +42,22 @@ int CSteamProto::MirandaToSteamState(int status)
return "play";*/
//case 1: //Online
default:
- return ID_STATUS_OFFLINE;
+ return ID_STATUS_ONLINE;
}
}
bool CSteamProto::IsOnline()
{
- return m_iStatus > ID_STATUS_OFFLINE;
+ return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread;
+}
+
+bool CSteamProto::IsMe(const char *steamId)
+{
+ ptrA mySteamId(getStringA("SteamID"));
+ if (!lstrcmpA(steamId, mySteamId))
+ return true;
+
+ return false;
}
void CSteamProto::SetServerStatusThread(void *arg)
@@ -72,15 +81,195 @@ void CSteamProto::SetServerStatusThread(void *arg)
if (sendResult.IsSuccess())
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus);
+ else
+ m_iStatus = oldStatus;
}
void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResult)
{
ptrW username(getWStringA("Username"));
- ptrA password(getStringA("Password"));
+ ptrA base64RsaEncryptedPassword;
+
+ DBVARIANT dbv;
+ CMStringA timestamp;
+ DWORD encryptedSize = 0;
+ BYTE *encryptedPassword = NULL;
+ db_get(NULL, this->m_szModuleName, "EncryptedPassword", &dbv);
+ if (dbv.type == DBVT_BLOB && dbv.pbVal && dbv.cpbVal > 0)
+ {
+ encryptedSize = dbv.cpbVal;
+ encryptedPassword = (BYTE*)mir_alloc(dbv.cpbVal);
+ memcpy(encryptedPassword, dbv.pbVal, dbv.cpbVal);
+
+ timestamp = getStringA("RsaTimestamp");
+ }
+ else
+ {
+ // get rsa public key
+ SteamWebApi::RsaKeyApi::RsaKey rsaKey;
+ SteamWebApi::RsaKeyApi::GetRsaKey(m_hNetlibUser, username, &rsaKey);
+ if (!rsaKey.IsSuccess())
+ {
+ db_free(&dbv);
+ return;
+ }
+
+ timestamp = rsaKey.GetTimestamp();
+ setString("RsaTimestamp", timestamp);
+
+ ptrA password(getStringA("Password"));
+
+ // OpenSSL rsa is depricated
+ /*BIGNUM *n = BN_new();
+ if (!BN_hex2bn(&n, rsaKey.GetModulus()))
+ {
+ BN_free(n);
+ return;
+ }
+
+ BIGNUM *e = BN_new();
+ if (!BN_hex2bn(&e, rsaKey.GetExponent()))
+ {
+ BN_free(e);
+ return;
+ }
+
+ RSA *rsa = RSA_new();
+ rsa->n = n;
+ rsa->e = e;
+
+ encryptedSize = RSA_size(rsa);
+ encryptedPassword = (BYTE*)mir_alloc(encryptedSize);
+ if (RSA_public_encrypt(strlen(password), (unsigned char*)(char*)password, encryptedPassword, rsa, RSA_PKCS1_PADDING) < 0)
+ {
+ RSA_free(rsa);
+ return;
+ }
+
+ BN_free(e);
+ BN_free(n);
+ RSA_free(rsa);*/
+
+ const char *pszModulus = rsaKey.GetModulus();
+ DWORD cchModulus = strlen(pszModulus);
+
+ // convert hex string to byte array
+ DWORD cbLen = 0, dwSkip = 0, dwFlags = 0;
+ if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, NULL, &cbLen, &dwSkip, &dwFlags))
+ {
+ DWORD dwResult = GetLastError();
+ int i = 0;
+ }
+
+ // Allocate a new buffer.
+ BYTE *pbBuffer = (BYTE*)malloc(cbLen);
+ if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, pbBuffer, &cbLen, &dwSkip, &dwFlags))
+ {
+ DWORD dwResult = GetLastError();
+ int i = 0;
+ }
+
+ // reverse byte array, because of microsoft
+ for (int i = 0; i < cbLen / 2; ++i)
+ {
+ BYTE temp = pbBuffer[cbLen - i - 1];
+ pbBuffer[cbLen - i - 1] = pbBuffer[i];
+ pbBuffer[i] = temp;
+ }
+
+ HCRYPTPROV hCSP = 0;
+ if (!CryptAcquireContext(&hCSP, NULL, NULL, PROV_RSA_AES, CRYPT_SILENT) ||
+ !CryptAcquireContext(&hCSP, NULL, NULL, PROV_RSA_AES, CRYPT_SILENT | CRYPT_NEWKEYSET))
+ {
+ DWORD dwResult = GetLastError();
+ int i = 0;
+ }
+
+ // Move the key into the key container.
+ DWORD cbKeyBlob = sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + cbLen;
+ BYTE *pKeyBlob = (BYTE*)malloc(cbKeyBlob);
+
+ // Fill in the data.
+ PUBLICKEYSTRUC *pPublicKey = (PUBLICKEYSTRUC*)pKeyBlob;
+ pPublicKey->bType = PUBLICKEYBLOB;
+ pPublicKey->bVersion = CUR_BLOB_VERSION; // Always use this value.
+ pPublicKey->reserved = 0; // Must be zero.
+ pPublicKey->aiKeyAlg = CALG_RSA_KEYX; // RSA public-key key exchange.
+
+ // The next block of data is the RSAPUBKEY structure.
+ RSAPUBKEY *pRsaPubKey = (RSAPUBKEY*)(pKeyBlob + sizeof(PUBLICKEYSTRUC));
+ pRsaPubKey->magic = 0x31415352; // RSA1 // Use public key
+ pRsaPubKey->bitlen = cbLen * 8; // Number of bits in the modulus.
+ pRsaPubKey->pubexp = 0x10001; // "010001" // Exponent.
+
+ // Copy the modulus into the blob. Put the modulus directly after the
+ // RSAPUBKEY structure in the blob.
+ BYTE *pKey = (BYTE*)(((BYTE *)pRsaPubKey) + sizeof(RSAPUBKEY));
+ //pKeyBlob + sizeof(BLOBHEADER)+ sizeof(RSAPUBKEY);
+ memcpy(pKey, pbBuffer, cbLen);
+
+ // Now import public key
+ HCRYPTKEY phKey = 0;
+ if (!CryptImportKey(hCSP, pKeyBlob, cbKeyBlob, 0, 0, &phKey))
+ {
+ DWORD err = GetLastError();
+ int i = 0;
+ }
+
+ // encrypt password
+ DWORD pwdLength = strlen(password);
+ if (!CryptEncrypt(phKey, 0, TRUE, 0, NULL, &encryptedSize, pwdLength))
+ {
+ DWORD err = GetLastError();
+ int i = 0;
+ }
+
+ encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
+ memcpy(encryptedPassword, password, pwdLength);
+ if (!CryptEncrypt(phKey, 0, TRUE, 0, encryptedPassword, &pwdLength, encryptedSize))
+ {
+ DWORD err = GetLastError();
+ int i = 0;
+ }
+
+ // reverse byte array again
+ for (int i = 0; i < encryptedSize / 2; ++i)
+ {
+ BYTE temp = encryptedPassword[encryptedSize - i - 1];
+ encryptedPassword[encryptedSize - i - 1] = encryptedPassword[i];
+ encryptedPassword[i] = temp;
+ }
+
+ // save rsa encrypted password to db
+ db_set_blob(NULL, this->m_szModuleName, "EncryptedPassword", encryptedPassword, encryptedSize);
+
+ CryptDestroyKey(phKey);
+ free(pKeyBlob);
+ CryptReleaseContext(hCSP, 0);
+ free(pbBuffer);
+ }
+ db_free(&dbv);
+
+ //DWORD cbLen = 0, dwSkip = 0, dwFlags = 0;
+ //if (!CryptBinaryToStringA(encryptedPassword, encryptedSize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, NULL, &cbLen))
+ //{
+ // DWORD dwResult = GetLastError();
+ // int i = 0;
+ //}
+
+ //// Allocate a new buffer.
+ //char *pbBuffer = (char*)malloc(cbLen);
+ //if (!CryptBinaryToStringA(encryptedPassword, encryptedSize, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, pbBuffer, &cbLen))
+ //{
+ // DWORD dwResult = GetLastError();
+ // int i = 0;
+ //}
+
+ base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
+ mir_free(encryptedPassword);
// try to authorize
- SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, password, authResult);
+ SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, base64RsaEncryptedPassword, timestamp, authResult);
if (authResult->IsEmailAuthNeeded() || authResult->IsCaptchaNeeded())
{
do
@@ -108,15 +297,18 @@ void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResul
}
// try to authorize with emailauthcode or captcha taxt
- SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, password, authResult);
+ SteamWebApi::AuthorizationApi::Authorize(m_hNetlibUser, username, base64RsaEncryptedPassword, timestamp, authResult);
} while (authResult->IsEmailAuthNeeded() || authResult->IsCaptchaNeeded());
}
}
void CSteamProto::LogInThread(void* param)
{
+ if (this->IsOnline())
+ return;
+
CMStringA token(getStringA("TokenSecret"));
- if (token.IsEmpty()/* && !this->IsOnline()*/)
+ if (token.IsEmpty())
{
SteamWebApi::AuthorizationApi::AuthResult authResult;
Authorize(&authResult);
@@ -154,13 +346,6 @@ void CSteamProto::LogInThread(void* param)
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iDesiredStatus);
}
- // start pooling thread
- if (m_hPollingThread == NULL && !m_bTerminated)
- {
- m_bTerminated = false;
- m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, NULL, NULL);
- }
-
// get contact list
SteamWebApi::FriendListApi::FriendList friendList;
SteamWebApi::FriendListApi::Load(m_hNetlibUser, token, loginResult.GetSteamId(), &friendList);
@@ -178,6 +363,13 @@ void CSteamProto::LogInThread(void* param)
}
}
}
+
+ // start pooling thread
+ if (m_hPollingThread == NULL && !m_bTerminated)
+ {
+ m_bTerminated = false;
+ m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, NULL, NULL);
+ }
}
void CSteamProto::LogOutThread(void*)
diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp
index 9e01da2e33..8e9aa87f9f 100644
--- a/protocols/Steam/src/steam_contacts.cpp
+++ b/protocols/Steam/src/steam_contacts.cpp
@@ -59,4 +59,46 @@ MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Friend &contact)
}
return hContact;
+}
+
+void CSteamProto::SearchByIdThread(void* arg)
+{
+ ptrW steamIdW((wchar_t*)arg);
+ ptrA steamId(mir_u2a(steamIdW));
+
+ ptrA token(getStringA("TokenSecret"));
+
+ SteamWebApi::FriendApi::Friend rFriend;
+ SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamId, &rFriend);
+
+ if (!rFriend.IsSuccess())
+ {
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)STEAM_SEARCH_BYID, 0);
+ return;
+ }
+
+ PROTOSEARCHRESULT psr = { 0 };
+ psr.cbSize = sizeof(psr);
+ psr.flags = PSR_TCHAR;
+
+ psr.id = mir_wstrdup(steamIdW);
+ psr.nick = mir_wstrdup(rFriend.GetNickname());
+
+ const wchar_t *realname = rFriend.GetRealname();
+ const wchar_t *p = wcschr(realname, ' ');
+ if (p == NULL)
+ psr.firstName = mir_wstrdup(realname);
+ else
+ {
+ int length = p - realname;
+ psr.firstName = (wchar_t*)mir_alloc(sizeof(wchar_t) * (length + 1));
+ wmemcpy(psr.firstName, realname, length);
+ psr.firstName[length] = '\0';
+ psr.lastName = mir_wstrdup(p + 1);
+ }
+
+ //psr.reserved[0] = &psr;
+
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)STEAM_SEARCH_BYID, (LPARAM)&psr);
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)STEAM_SEARCH_BYID, 0);
} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp
index 7b5b808339..6fe6ac82e9 100644
--- a/protocols/Steam/src/steam_proto.cpp
+++ b/protocols/Steam/src/steam_proto.cpp
@@ -36,6 +36,10 @@ CSteamProto::~CSteamProto()
MCONTACT __cdecl CSteamProto::AddToList(int flags, PROTOSEARCHRESULT* psr)
{
+ /*CContact::Ref contact;
+ this->GetContact((char *)mir_ptr<char>(::mir_utf8encodeW(psr->id)), contact);
+ return this->AddContact(contact);*/
+
return 0;
}
@@ -89,7 +93,7 @@ DWORD_PTR __cdecl CSteamProto:: GetCaps(int type, MCONTACT hContact)
switch(type)
{
case PFLAGNUM_1:
- return PF1_IM;
+ return PF1_IM | PF1_BASICSEARCH;
case PFLAGNUM_2:
return PF2_ONLINE;
case PFLAG_UNIQUEIDTEXT:
@@ -105,7 +109,12 @@ int __cdecl CSteamProto::GetInfo(MCONTACT hContact, int infoType ) { return 0; }
HANDLE __cdecl CSteamProto::SearchBasic(const TCHAR* id)
{
- return 0;
+ if (!this->IsOnline())
+ return 0;
+
+ ForkThread(&CSteamProto::SearchByIdThread, mir_wstrdup(id));
+
+ return (HANDLE)STEAM_SEARCH_BYID;
}
HANDLE __cdecl CSteamProto::SearchByEmail(const TCHAR* email)
@@ -211,6 +220,7 @@ int CSteamProto::SetStatus(int new_status)
if (IsOnline())
{
ForkThread(&CSteamProto::SetServerStatusThread, &new_status);
+
return 0;
}
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h
index e3cc2ea3d2..d6e579a2fb 100644
--- a/protocols/Steam/src/steam_proto.h
+++ b/protocols/Steam/src/steam_proto.h
@@ -1,6 +1,9 @@
#ifndef _STEAM_PROTO_H_
#define _STEAM_PROTO_H_
+#define STEAM_SEARCH_BYID 1001
+#define STEAM_SEARCH_BYNAME 1002
+
struct GuardParam
{
char code[10];
@@ -90,7 +93,7 @@ protected:
static int CompareProtos(const CSteamProto *p1, const CSteamProto *p2);
// pooling thread
- int PollStatus(const char *sessionId, const char *steamId, UINT32 messageId);
+ void PollStatus(const char *sessionId, const char *steamId, UINT32 messageId, SteamWebApi::PollApi::PollResult *pollResult);
void __cdecl PollingThread(void*);
// account
@@ -98,6 +101,7 @@ protected:
static int MirandaToSteamState(int status);
bool IsOnline();
+ bool IsMe(const char *steamId);
void Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResult);
void __cdecl LogInThread(void*);
void __cdecl LogOutThread(void*);
@@ -110,6 +114,8 @@ protected:
MCONTACT FindContact(const char *steamId);
MCONTACT AddContact(const SteamWebApi::FriendApi::Friend &contact);
+ void __cdecl SearchByIdThread(void*);
+
// messages
void __cdecl SendMessageThread(void*);
void __cdecl SendTypingThread(void*);
diff --git a/protocols/Steam/src/steam_thread.cpp b/protocols/Steam/src/steam_thread.cpp
index 4bb62c23d7..3249ef629e 100644
--- a/protocols/Steam/src/steam_thread.cpp
+++ b/protocols/Steam/src/steam_thread.cpp
@@ -1,34 +1,23 @@
#include "common.h"
-int CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 messageId)
+void CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 messageId, SteamWebApi::PollApi::PollResult *pollResult)
{
- SteamWebApi::PollApi::PollResult pollResult;
- SteamWebApi::PollApi::PollStatus(m_hNetlibUser, token, sessionId, messageId, &pollResult);
-
- if (!pollResult.IsSuccess())
- return 0;
-
- if (pollResult.IsNeedRelogin())
- {
- SteamWebApi::LoginApi::LoginResult loginResult;
- SteamWebApi::LoginApi::Logon(m_hNetlibUser, token, &loginResult);
-
- if (!loginResult.IsSuccess())
- return 0;
+ SteamWebApi::PollApi::PollStatus(m_hNetlibUser, token, sessionId, messageId, pollResult);
- return messageId;
- }
+ if (!pollResult->IsSuccess())
+ return;
- for (int i = 0; i < pollResult.GetItemCount(); i++)
+ for (int i = 0; i < pollResult->GetItemCount(); i++)
{
- switch (pollResult[i]->GetType())
+ const SteamWebApi::PollApi::PoolItem *item = pollResult->operator[](i);
+ switch (item->GetType())
{
- case SteamWebApi::PollApi::POOL_TYPE::TYPING:
+ case SteamWebApi::PollApi::POOL_TYPE_TYPING:
break;
- case SteamWebApi::PollApi::POOL_TYPE::MESSAGE:
+ case SteamWebApi::PollApi::POOL_TYPE_MESSAGE:
{
- SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)pollResult[i];
+ SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)item;
MCONTACT hContact = FindContact(message->GetSteamId());
if (hContact)
@@ -45,9 +34,9 @@ int CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 mes
}
break;
- case SteamWebApi::PollApi::POOL_TYPE::MYMESSAGE:
+ case SteamWebApi::PollApi::POOL_TYPE_MYMESSAGE:
{
- SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)pollResult[i];
+ SteamWebApi::PollApi::Message *message = (SteamWebApi::PollApi::Message*)item;
MCONTACT hContact = FindContact(message->GetSteamId());
if (hContact)
@@ -67,31 +56,31 @@ int CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 mes
}
break;
- case SteamWebApi::PollApi::POOL_TYPE::STATE:
+ case SteamWebApi::PollApi::POOL_TYPE_STATE:
{
- SteamWebApi::PollApi::State *state = (SteamWebApi::PollApi::State*)pollResult[i];
+ SteamWebApi::PollApi::State *state = (SteamWebApi::PollApi::State*)item;
WORD status = CSteamProto::SteamToMirandaStatus(state->GetStatus());
- const char *cSteamId = state->GetSteamId();
+ const char *steamId = state->GetSteamId();
const wchar_t *nickname = state->GetNickname();
- ptrA steamId(getStringA("SteamID"));
- if (!lstrcmpA(steamId, cSteamId))
+ if (IsMe(steamId))
{
const wchar_t *oldNickname = getWStringA("Nick");
if (lstrcmp(oldNickname, nickname))
setWString("Nick", nickname);
- SetStatus(status);
-
+
+ SetStatus(status);
}
else
{
- MCONTACT hContact = FindContact(cSteamId);
+ MCONTACT hContact = FindContact(steamId);
if (hContact)
{
const wchar_t *oldNickname = getWStringA(hContact, "Nick");
if (lstrcmp(oldNickname, nickname))
setWString(hContact, "Nick", nickname);
+
SetContactStatus(hContact, status);
}
}
@@ -99,8 +88,6 @@ int CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 mes
break;
}
}
-
- return pollResult.GetMessageId();
}
void CSteamProto::PollingThread(void*)
@@ -111,15 +98,34 @@ void CSteamProto::PollingThread(void*)
ptrA sessionId(getStringA("SessionID"));
UINT32 messageId = getDword("MessageID", 0);
+ SteamWebApi::PollApi::PollResult pollResult;
while (!m_bTerminated)
{
- messageId = PollStatus(token, sessionId, messageId);
- if (messageId == 0)
+ PollStatus(token, sessionId, messageId, &pollResult);
+
+ if (pollResult.IsNeedRelogin())
+ debugLogA("CSteamProto::PollingThread: need to relogin");
+ /*{
+ SteamWebApi::LoginApi::LoginResult loginResult;
+ SteamWebApi::LoginApi::Logon(m_hNetlibUser, token, &loginResult);
+
+ if (!loginResult.IsSuccess())
+ break;
+
+ sessionId = mir_strdup(loginResult.GetSessionId());
+ setString("SessionID", sessionId);
+ }*/
+
+ if (!pollResult.IsSuccess())
break;
+
+ messageId = pollResult.GetMessageId();
}
- if (messageId > 0)
+ if (pollResult.IsSuccess())
setDword("MessageID", messageId);
+ else
+ SetStatus(ID_STATUS_OFFLINE);
m_hPollingThread = NULL;
debugLogA("CSteamProto::PollingThread: leaving");