diff options
21 files changed, 526 insertions, 322 deletions
diff --git a/protocols/Steam/Steam_10.vcxproj b/protocols/Steam/Steam_10.vcxproj index 3660f2db5c..62342a80da 100644 --- a/protocols/Steam/Steam_10.vcxproj +++ b/protocols/Steam/Steam_10.vcxproj @@ -215,6 +215,7 @@ <PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\steam_thread.cpp" />
+ <ClCompile Include="src\steam_utils.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 4513b5e30e..4303fa4594 100644 --- a/protocols/Steam/Steam_10.vcxproj.filters +++ b/protocols/Steam/Steam_10.vcxproj.filters @@ -45,6 +45,9 @@ <ClCompile Include="src\steam_messages.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\steam_utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h">
diff --git a/protocols/Steam/Steam_12.vcxproj b/protocols/Steam/Steam_12.vcxproj index c4cbfb26de..4e9d7a373b 100644 --- a/protocols/Steam/Steam_12.vcxproj +++ b/protocols/Steam/Steam_12.vcxproj @@ -218,6 +218,7 @@ <PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\steam_thread.cpp" />
+ <ClCompile Include="src\steam_utils.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="res\Version.rc" />
diff --git a/protocols/Steam/Steam_12.vcxproj.filters b/protocols/Steam/Steam_12.vcxproj.filters index 5c30306822..04374351bd 100644 --- a/protocols/Steam/Steam_12.vcxproj.filters +++ b/protocols/Steam/Steam_12.vcxproj.filters @@ -45,6 +45,9 @@ <ClCompile Include="src\steam_messages.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\steam_utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h">
diff --git a/protocols/Steam/src/Steam/authorization.h b/protocols/Steam/src/Steam/authorization.h index f7fa0444ee..e9b1733107 100644 --- a/protocols/Steam/src/Steam/authorization.h +++ b/protocols/Steam/src/Steam/authorization.h @@ -77,14 +77,17 @@ namespace SteamWebApi data.AppendFormat("&oauth_scope=%s", "read_profile write_profile read_client write_client");
data.Append("&oauth_client_id=DE45CD61");
- HttpRequest request(hConnection, REQUEST_POST, STEAM_COMMUNITY_URL "/mobilelogin/dologin");
+ HttpRequest request(hConnection, REQUEST_POST, STEAM_COM_URL "/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)
+ if (!response)
+ return;
+
+ if ((authResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
-
+
JSONNODE *root = json_parse(response->pData), *node;
node = json_get(root, "success");
@@ -123,10 +126,7 @@ namespace SteamWebApi 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);
+ root = json_parse(ptrA(mir_u2a(json_as_string(node))));
node = json_get(root, "steamid");
authResult->steamid = ptrA(mir_u2a(json_as_string(node)));
@@ -134,8 +134,8 @@ namespace SteamWebApi node = json_get(root, "oauth_token");
authResult->token = ptrA(mir_u2a(json_as_string(node)));
- node = json_get(root, "webcookie");
- authResult->cookie = ptrA(mir_u2a(json_as_string(node)));
+ /*node = json_get(root, "webcookie");
+ authResult->cookie = ptrA(mir_u2a(json_as_string(node)));*/
authResult->success = true;
authResult->captcha_needed = false;
diff --git a/protocols/Steam/src/Steam/friend.h b/protocols/Steam/src/Steam/friend.h index 2c89dd718a..c01226e823 100644 --- a/protocols/Steam/src/Steam/friend.h +++ b/protocols/Steam/src/Steam/friend.h @@ -6,7 +6,7 @@ namespace SteamWebApi class FriendApi : public BaseApi
{
public:
- struct Friend : public Result
+ struct Summary : public Result
{
friend FriendApi;
@@ -36,18 +36,31 @@ namespace SteamWebApi const DWORD GetLastEvent() const { return lastEvent; }
};
- static void LoadSummaries(HANDLE hConnection, const char *token, const char *steamId, Friend *result)
+ struct Summaries : public Result
{
- result->success = false;
+ friend FriendApi;
+
+ private:
+ std::vector<Summary*> items;
- HttpRequest *request = new HttpRequest(hConnection, REQUEST_GET, STEAM_API_URL "/ISteamUserOAuth/GetUserSummaries/v0001");
- request->AddParameter("access_token", token);
- request->AddParameter("steamids", steamId);
+ public:
+ int GetItemCount() const { return items.size(); }
+ const Summary *GetAt(int idx) const { return items.at(idx); }
+ };
- mir_ptr<NETLIBHTTPREQUEST> response(request->Send());
- delete request;
+ static void LoadSummaries(HANDLE hConnection, const char *token, const char *steamIds, Summaries *summaries)
+ {
+ summaries->success = false;
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ HttpRequest request(hConnection, REQUEST_GET, STEAM_API_URL "/ISteamUserOAuth/GetUserSummaries/v0001");
+ request.AddParameter("access_token", token);
+ request.AddParameter("steamids", steamIds);
+
+ mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
+ if (!response)
+ return;
+
+ if ((summaries->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
JSONNODE *root = json_parse(response->pData), *node, *child;
@@ -62,43 +75,44 @@ namespace SteamWebApi if (child == NULL)
break;
+ Summary *item = new Summary();
+
node = json_get(child, "steamid");
- ptrA cSteamId(ptrA(mir_u2a(json_as_string(node))));
- if (lstrcmpA(steamId, cSteamId))
- return;
- result->steamId = steamId;
+ item->steamId = ptrA(mir_u2a(json_as_string(node)));
node = json_get(child, "personaname");
- result->nickname = json_as_string(node);
+ item->nickname = json_as_string(node);
node = json_get(child, "realname");
if (node != NULL)
- result->realname = json_as_string(node);
+ item->realname = json_as_string(node);
node = json_get(child, "loccountrycode");
if (node != NULL)
- result->countryCode = ptrA(mir_u2a(json_as_string(node)));
+ item->countryCode = ptrA(mir_u2a(json_as_string(node)));
node = json_get(child, "personastate");
- result->state = json_as_int(node);
+ item->state = json_as_int(node);
node = json_get(child, "profileurl");
- result->homepage = ptrA(mir_u2a(json_as_string(node)));
+ item->homepage = ptrA(mir_u2a(json_as_string(node)));
node = json_get(child, "timecreated");
- result->created = json_as_int(node);
+ item->created = json_as_int(node);
node = json_get(child, "lastlogoff");
- result->lastEvent = json_as_int(node);
+ item->lastEvent = json_as_int(node);
node = json_get(child, "avatarfull");
- result->avatarUrl = ptrA(mir_u2a(json_as_string(node)));
+ item->avatarUrl = ptrA(mir_u2a(json_as_string(node)));
+
+ summaries->items.push_back(item);
}
}
else
return;
- result->success = true;
+ summaries->success = true;
}
};
}
diff --git a/protocols/Steam/src/Steam/friend_list.h b/protocols/Steam/src/Steam/friend_list.h index 5cd683fa9b..59df8918b0 100644 --- a/protocols/Steam/src/Steam/friend_list.h +++ b/protocols/Steam/src/Steam/friend_list.h @@ -28,7 +28,10 @@ namespace SteamWebApi request.AddParameter("steamid", steamId);
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((friendList->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
JSONNODE *root = json_parse(response->pData), *node, *child;
diff --git a/protocols/Steam/src/Steam/login.h b/protocols/Steam/src/Steam/login.h index a6f743c45c..d46e0a8e52 100644 --- a/protocols/Steam/src/Steam/login.h +++ b/protocols/Steam/src/Steam/login.h @@ -28,16 +28,19 @@ namespace SteamWebApi CMStringA data;
data.AppendFormat("access_token=%s", token);
- data.Append("&ui_mode=web");
+ //data.Append("&ui_mode=web");
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)
+ if (!response)
return;
-
+
+ if ((loginResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
+ return;
+
JSONNODE *root = json_parse(response->pData), *node;
node = json_get(root, "error");
diff --git a/protocols/Steam/src/Steam/message.h b/protocols/Steam/src/Steam/message.h index d5059c4833..d390049e4c 100644 --- a/protocols/Steam/src/Steam/message.h +++ b/protocols/Steam/src/Steam/message.h @@ -34,7 +34,10 @@ namespace SteamWebApi request.SetData(data.GetBuffer(), data.GetLength());
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((sendResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
sendResult->success = true;
@@ -56,7 +59,10 @@ namespace SteamWebApi request.SetData(data.GetBuffer(), data.GetLength());
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((sendResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
JSONNODE *root = json_parse(response->pData), *node;
@@ -88,7 +94,10 @@ namespace SteamWebApi request.SetData(data.GetBuffer(), data.GetLength());
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((sendResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
sendResult->success = true;
diff --git a/protocols/Steam/src/Steam/poll.h b/protocols/Steam/src/Steam/poll.h index f5b0c602ea..78d337d388 100644 --- a/protocols/Steam/src/Steam/poll.h +++ b/protocols/Steam/src/Steam/poll.h @@ -16,7 +16,7 @@ namespace SteamWebApi //POOL_TYPE_RELATIONSHIP
};
- class PoolItem : public Result
+ class PoolItem// : public Result
{
friend PollApi;
@@ -74,7 +74,7 @@ namespace SteamWebApi UINT32 GetMessageId() const { return messageId; }
int IsNeedRelogin() const { return need_relogin; }
int GetItemCount() const { return items.size(); }
- const PoolItem * operator[](int idx) const { return items.at(idx); }
+ const PoolItem *GetAt(int idx) const { return items.at(idx); }
};
static void PollStatus(HANDLE hConnection, const char *token, const char *sessionId, UINT32 messageId, PollResult *pollResult)
@@ -91,10 +91,13 @@ namespace SteamWebApi 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; // may need to encrease timeout
+ request.SetTimeout(90000); // may need to encrease timeout
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((pollResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
JSONNODE *root = json_parse(response->pData), *node, *child;
diff --git a/protocols/Steam/src/Steam/rsa_key.h b/protocols/Steam/src/Steam/rsa_key.h index a5322d3523..60efe6ee47 100644 --- a/protocols/Steam/src/Steam/rsa_key.h +++ b/protocols/Steam/src/Steam/rsa_key.h @@ -1,20 +1,6 @@ #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
@@ -42,11 +28,14 @@ namespace SteamWebApi ptrA base64Username(mir_urlEncode(ptrA(mir_utf8encodeW(username))));
- HttpRequest request(hConnection, REQUEST_GET, STEAM_COMMUNITY_URL "/mobilelogin/getrsakey");
+ HttpRequest request(hConnection, REQUEST_GET, STEAM_COM_URL "/mobilelogin/getrsakey");
request.AddParameter("username", (char*)base64Username);
-
+
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
+ return;
+
+ if ((rsaKey->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
return;
JSONNODE *root = json_parse(response->pData), *node;
diff --git a/protocols/Steam/src/Steam/search.h b/protocols/Steam/src/Steam/search.h index ad4bd9c5d9..dc6f6c0487 100644 --- a/protocols/Steam/src/Steam/search.h +++ b/protocols/Steam/src/Steam/search.h @@ -7,8 +7,15 @@ namespace SteamWebApi {
public:
- class SearchItem : public Result
+ class SearchItem// : public Result
{
+ friend SearchApi;
+
+ private:
+ std::string steamId;
+
+ public:
+ const char *GetSteamId() const { return steamId.c_str(); }
};
class SearchResult : public Result
@@ -22,7 +29,8 @@ namespace SteamWebApi public:
SearchResult() : count(0) { }
- int GetCount() { return count; }
+ int GetItemCount() { return count; }
+ const SearchItem *GetAt(int idx) const { return items.at(idx); }
};
static void Search(HANDLE hConnection, const char *token, const char *text, SearchResult *searchResult)
@@ -31,15 +39,20 @@ namespace SteamWebApi searchResult->count = 0;
searchResult->items.clear();
+ // todo: may need to load all results
+ // 15 first at now
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");
-
+ request.AddParameter("access_token", token);
+ request.AddParameter("keywords", ptrA(mir_urlEncode(text)));
+ request.AddParameter("offset=0&count=15&targets=users&fields=all");
+
mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- if (!response || response->resultCode != HTTP_STATUS_OK)
+ if (!response)
return;
-
+
+ if ((searchResult->status = (HTTP_STATUS)response->resultCode) != HTTP_STATUS_OK)
+ return;
+
JSONNODE *root = json_parse(response->pData), *node, *child;;
node = json_get(root, "success");
@@ -66,7 +79,12 @@ namespace SteamWebApi if (child == NULL)
break;
- SearchItem *item = NULL;
+ SearchItem *item = new SearchItem();
+
+ node = json_get(child, "steamid");
+ item->steamId = ptrA(mir_u2a(json_as_string(node)));
+
+ searchResult->items.push_back(item);
}
}
diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h index acdb86393d..8ff9a645d2 100644 --- a/protocols/Steam/src/Steam/steam.h +++ b/protocols/Steam/src/Steam/steam.h @@ -4,7 +4,7 @@ namespace SteamWebApi
{
#define STEAM_API_URL "https://api.steampowered.com"
- #define STEAM_COMMUNITY_URL "https://steamcommunity.com"
+ #define STEAM_COM_URL "https://steamcommunity.com"
struct Result
{
@@ -18,10 +18,13 @@ namespace SteamWebApi {
protected:
bool success;
+ HTTP_STATUS status;
public:
- Result() : success(false) { }
+ Result() : success(false), status(HTTP_STATUS_NONE) { }
+
bool IsSuccess() const { return success; }
+ HTTP_STATUS GetStatus() const { return status; }
};
};
}
diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h index f69b524c8a..2e3f9e17a2 100644 --- a/protocols/Steam/src/http_request.h +++ b/protocols/Steam/src/http_request.h @@ -5,7 +5,8 @@ enum HTTP_STATUS
{
- HTTP_STATUS_OK = 200/*,
+ HTTP_STATUS_NONE = 0,
+ HTTP_STATUS_OK = 200,
HTTP_STATUS_BAD_REQUEST = 400,
HTTP_STATUS_UNAUTHORIZED = 401,
HTTP_STATUS_FORBIDDEN = 403,
@@ -13,10 +14,10 @@ enum HTTP_STATUS HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
HTTP_STATUS_TOO_MANY_REQUESTS = 429,
HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
- HTTP_STATUS_INSUFICIENTE_STORAGE = 507*/
+ HTTP_STATUS_INSUFICIENTE_STORAGE = 507
};
-class HttpRequest : public NETLIBHTTPREQUEST//, public MZeroedObject
+class HttpRequest : protected NETLIBHTTPREQUEST//, public MZeroedObject
{
public:
HttpRequest(HANDLE hNetlibUser, int request, LPCSTR url)
@@ -74,48 +75,6 @@ public: memcpy(pData, data, size);
}
- /*void AddBasicAuthHeader(LPCSTR szLogin, LPCSTR szPassword)
- {
- char cPair[128];
- mir_snprintf(
- cPair,
- SIZEOF(cPair),
- "%s:%s",
- szLogin,
- szPassword);
-
- char *ePair = (char *)mir_base64_encode((BYTE*)cPair, (UINT)strlen(cPair));
-
- char value[128];
- mir_snprintf(
- value,
- SIZEOF(value),
- "Basic %s",
- ePair);
-
- mir_free(ePair);
-
- headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount+1));
- headers[headersCount].szName = mir_strdup("Authorization");
- headers[headersCount].szValue = mir_strdup(value);
- headersCount++;
- }
-
- void AddBearerAuthHeader(LPCSTR szValue)
- {
- char value[128];
- mir_snprintf(
- value,
- SIZEOF(value),
- "Bearer %s",
- szValue);
-
- headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount+1));
- headers[headersCount].szName = mir_strdup("Authorization");
- headers[headersCount].szValue = mir_strdup(value);
- headersCount++;
- }*/
-
void AddUrlPart(LPCSTR szPart)
{
m_szUrl += szPart;
@@ -153,6 +112,11 @@ public: m_szUrl.AppendFormat("&%s", szValue);
}
+ void SetTimeout(int timeout)
+ {
+ timeout = timeout;
+ }
+
NETLIBHTTPREQUEST *Send()
{
szUrl = m_szUrl.GetBuffer();
diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp index c0686cf7bd..812b9a75b5 100644 --- a/protocols/Steam/src/steam_account.cpp +++ b/protocols/Steam/src/steam_account.cpp @@ -1,51 +1,5 @@ #include "common.h"
-WORD CSteamProto::SteamToMirandaStatus(int state)
-{
- switch (state)
- {
- case 0: //Offline
- return ID_STATUS_OFFLINE;
- case 2: //Busy
- return ID_STATUS_DND;
- case 3: //Away
- return ID_STATUS_AWAY;
- /*case 4: //Snoozing
- prim = PURPLE_STATUS_EXTENDED_AWAY;
- break;
- case 5: //Looking to trade
- return "trade";
- case 6: //Looking to play
- return "play";*/
- //case 1: //Online
- default:
- return ID_STATUS_ONLINE;
- }
-}
-
-int CSteamProto::MirandaToSteamState(int status)
-{
- switch (status)
- {
- case ID_STATUS_OFFLINE:
- return 0; //Offline
- case ID_STATUS_DND:
- return 2; //Busy
- case ID_STATUS_AWAY:
- return 3; //Away
- /*case 4: //Snoozing
- prim = PURPLE_STATUS_EXTENDED_AWAY;
- break;
- case 5: //Looking to trade
- return "trade";
- case 6: //Looking to play
- return "play";*/
- //case 1: //Online
- default:
- return ID_STATUS_ONLINE;
- }
-}
-
bool CSteamProto::IsOnline()
{
return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread;
@@ -94,8 +48,6 @@ void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResul if (lstrlen(nickname) == 0 && username)
setWString("Nick", username);
- return;
-
// get rsa public key
SteamWebApi::RsaKeyApi::RsaKey rsaKey;
SteamWebApi::RsaKeyApi::GetRsaKey(m_hNetlibUser, username, &rsaKey);
@@ -104,105 +56,21 @@ void CSteamProto::Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResul ptrA password(getStringA("Password"));
- 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))
- {
- debugLogA("CSteamProto::Authorize: Cannot get size of rsa modulus in binary (%lu)", GetLastError());
- return;
- }
-
- // Allocate a new buffer.
- BYTE *pbBuffer = (BYTE*)malloc(cbLen);
- if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, pbBuffer, &cbLen, &dwSkip, &dwFlags))
- {
- debugLogA("CSteamProto::Authorize: Cannot convert rsa modulus to binary (%lu)", GetLastError());
- return;
- }
-
- // 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))
- {
- debugLogA("CSteamProto::Authorize: Cannot create rsa context (%lu)", GetLastError());
- return;
- }
-
- // 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))
- {
- debugLogA("CSteamProto::Authorize: Cannot import rsa key to context (%lu)", GetLastError());
- return;
- }
-
- // encrypt password
+ DWORD error = 0;
DWORD encryptedSize = 0;
- DWORD pwdLength = strlen(password);
- if (!CryptEncrypt(phKey, 0, TRUE, 0, NULL, &encryptedSize, pwdLength))
+ if ((error = RsaEncrypt(rsaKey, password, strlen(password), NULL, encryptedSize)) != 0)
{
- debugLogA("CSteamProto::Authorize: Cannot get rsa encrypt length (%lu)", GetLastError());
+ debugLogA("CSteamProto::Rsa: encryption error (%lu)", error);
return;
}
BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
- memcpy(encryptedPassword, password, pwdLength);
- if (!CryptEncrypt(phKey, 0, TRUE, 0, encryptedPassword, &pwdLength, encryptedSize))
+ if ((error = RsaEncrypt(rsaKey, password, strlen(password), encryptedPassword, encryptedSize)) != 0)
{
- debugLogA("CSteamProto::Authorize: Cannot rsa encrypt password (%lu)", GetLastError());
+ debugLogA("CSteamProto::Rsa: encryption error (%lu)", error);
return;
}
- // 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);
-
base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
mir_free(encryptedPassword);
@@ -245,8 +113,8 @@ void CSteamProto::LogInThread(void* param) if (this->IsOnline())
return;
- CMStringA token(getStringA("TokenSecret"));
- if (token.IsEmpty())
+ ptrA token(getStringA("TokenSecret"));
+ if (!token || lstrlenA(token) == 0)
{
SteamWebApi::AuthorizationApi::AuthResult authResult;
Authorize(&authResult);
@@ -262,31 +130,40 @@ void CSteamProto::LogInThread(void* param) return;
}
- token = authResult.GetToken();
+ token = mir_strdup(authResult.GetToken());
+
setString("TokenSecret", token);
- setString("Cookie", authResult.GetCookie());
+ //setString("Cookie", authResult.GetCookie());
setString("SteamID", authResult.GetSteamid());
}
SteamWebApi::LoginApi::LoginResult loginResult;
SteamWebApi::LoginApi::Logon(m_hNetlibUser, token, &loginResult);
+
// if some error
if (!loginResult.IsSuccess())
{
- debugLogA("CSteamProto::login: Error");
+ debugLogA("CSteamProto::Login: Error (%d)", loginResult.GetStatus());
+
+ // token has expired
+ if (loginResult.GetStatus() == HTTP_STATUS_UNAUTHORIZED)
+ {
+ delSetting("TokenSecret");
+ delSetting("Cookie");
+ }
+
// set status to offline
m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE;
ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, ID_STATUS_OFFLINE);
return;
}
- else
- {
- setString("SessionID", loginResult.GetSessionId());
- setDword("MessageID", loginResult.GetMessageId());
- // set selected status
- m_iStatus = m_iDesiredStatus;
- ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iDesiredStatus);
- }
+
+ setString("SessionID", loginResult.GetSessionId());
+ setDword("MessageID", loginResult.GetMessageId());
+
+ // set selected status
+ m_iStatus = m_iDesiredStatus;
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iDesiredStatus);
// get contact list
SteamWebApi::FriendListApi::FriendList friendList;
@@ -298,10 +175,11 @@ void CSteamProto::LogInThread(void* param) {
if (!FindContact(friendList[i]))
{
- SteamWebApi::FriendApi::Friend rFriend;
+ // todo
+ /*SteamWebApi::FriendApi::Friend rFriend;
SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, friendList[i], &rFriend);
if (!rFriend.IsSuccess()) continue;
- AddContact(rFriend);
+ AddContact(rFriend);*/
}
}
}
diff --git a/protocols/Steam/src/steam_contacts.cpp b/protocols/Steam/src/steam_contacts.cpp index 8e9aa87f9f..6038ca029c 100644 --- a/protocols/Steam/src/steam_contacts.cpp +++ b/protocols/Steam/src/steam_contacts.cpp @@ -18,6 +18,66 @@ void CSteamProto::SetAllContactsStatus(WORD status) }
}
+void CSteamProto::UpdateContact(MCONTACT hContact, const SteamWebApi::FriendApi::Summary *contact)
+{
+ if (hContact && !FindContact(contact->GetSteamId()))
+ return;
+
+ // set common data
+ setWString(hContact, "Nick", contact->GetNickname());
+ setWord(hContact, "Status", SteamToMirandaStatus(contact->GetState()));
+ setString(hContact, "Homepage", contact->GetHomepage());
+ setDword(hContact, "LastEventDateTS", contact->GetLastEvent());
+
+ // set name
+ ptrW realname(mir_wstrdup(contact->GetRealname()));
+ const wchar_t *p = wcschr(realname, ' ');
+ if (p == NULL)
+ setWString(hContact, "FirstName", realname);
+ else
+ {
+ int length = p - (wchar_t*)realname;
+ realname[length] = '\0';
+ setWString(hContact, "LastName", realname);
+ setWString(hContact, "LastName", p + 1);
+ }
+
+ // set country
+ const char *isoCode = contact->GetCountryCode();
+ if (!lstrlenA(isoCode))
+ this->delSetting(hContact, "Country");
+ else
+ {
+ // todo: is should be free()?
+ char *country = (char *)CallService(MS_UTILS_GETCOUNTRYBYISOCODE, (WPARAM)isoCode, 0);
+ setString(hContact, "Country", country);
+ }
+}
+
+void CSteamProto::UpdateContactsThread(void *arg)
+{
+ ptrA steamIds((char*)arg);
+
+ ptrA token(getStringA("TokenSecret"));
+
+ SteamWebApi::FriendApi::Summaries summarues;
+ SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamIds, &summarues);
+
+ if (!summarues.IsSuccess())
+ return;
+
+ for (int i = 0; i < summarues.GetItemCount(); i++)
+ {
+ const SteamWebApi::FriendApi::Summary *contact = summarues.GetAt(i);
+
+ MCONTACT hContact = this->FindContact(contact->GetSteamId());
+ if (!hContact)
+ {
+ UpdateContact(hContact, contact);
+ }
+ }
+}
+
MCONTACT CSteamProto::FindContact(const char *steamId)
{
MCONTACT hContact = NULL;
@@ -36,20 +96,19 @@ MCONTACT CSteamProto::FindContact(const char *steamId) return hContact;
}
-MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Friend &contact)
+MCONTACT CSteamProto::AddContact(const SteamWebApi::FriendApi::Summary *contact)
{
- MCONTACT hContact = this->FindContact(contact.GetSteamId());
+ MCONTACT hContact = this->FindContact(contact->GetSteamId());
if (!hContact)
{
+ // create contact
hContact = (MCONTACT)CallService(MS_DB_CONTACT_ADD, 0, 0);
CallService(MS_PROTO_ADDTOCONTACT, hContact, (LPARAM)this->m_szModuleName);
- setString(hContact, "SteamID", contact.GetSteamId());
- setWString(hContact, "Nick", contact.GetNickname());
- setString(hContact, "Homepage", contact.GetHomepage());
- setDword(hContact, "LastEventDateTS", contact.GetLastEvent());
- db_set_ws(hContact, "CList", "MyHandle", contact.GetNickname());
+ // update info
+ UpdateContact(hContact, contact);
+ // move to default group
DBVARIANT dbv;
if (!getWString("DefaultGroup", &dbv))
{
@@ -68,37 +127,109 @@ void CSteamProto::SearchByIdThread(void* arg) ptrA token(getStringA("TokenSecret"));
- SteamWebApi::FriendApi::Friend rFriend;
- SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamId, &rFriend);
+ SteamWebApi::FriendApi::Summaries summarues;
+ SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamId, &summarues);
- if (!rFriend.IsSuccess())
+ if (!summarues.IsSuccess())
{
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)STEAM_SEARCH_BYID, 0);
return;
}
- PROTOSEARCHRESULT psr = { 0 };
- psr.cbSize = sizeof(psr);
- psr.flags = PSR_TCHAR;
+ if (summarues.GetItemCount() == 0)
+ return;
+
+ const SteamWebApi::FriendApi::Summary *contact = summarues.GetAt(0);
- psr.id = mir_wstrdup(steamIdW);
- psr.nick = mir_wstrdup(rFriend.GetNickname());
+ STEAM_SEARCH_RESULT ssr = { 0 };
+ ssr.hdr.cbSize = sizeof(STEAM_SEARCH_RESULT);
+ ssr.hdr.flags = PSR_TCHAR;
+
+ ssr.hdr.id = mir_wstrdup(steamIdW);
+ ssr.hdr.nick = mir_wstrdup(contact->GetNickname());
- const wchar_t *realname = rFriend.GetRealname();
+ const wchar_t *realname = contact->GetRealname();
const wchar_t *p = wcschr(realname, ' ');
if (p == NULL)
- psr.firstName = mir_wstrdup(realname);
+ ssr.hdr.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);
+ ssr.hdr.firstName = (wchar_t*)mir_alloc(sizeof(wchar_t) * (length + 1));
+ wmemcpy(ssr.hdr.firstName, realname, length);
+ ssr.hdr.firstName[length] = '\0';
+ ssr.hdr.lastName = mir_wstrdup(p + 1);
}
+
+ ssr.contact = contact;
- //psr.reserved[0] = &psr;
-
- ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)STEAM_SEARCH_BYID, (LPARAM)&psr);
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)STEAM_SEARCH_BYID, (LPARAM)&ssr);
ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)STEAM_SEARCH_BYID, 0);
+}
+
+void CSteamProto::SearchByNameThread(void* arg)
+{
+ ptrW keywordsW((wchar_t*)arg);
+ ptrA keywords(mir_utf8encodeW(keywordsW));
+
+ ptrA token(getStringA("TokenSecret"));
+
+ SteamWebApi::SearchApi::SearchResult searchResult;
+ SteamWebApi::SearchApi::Search(m_hNetlibUser, token, keywords, &searchResult);
+
+ if (!searchResult.IsSuccess())
+ {
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)STEAM_SEARCH_BYNAME, 0);
+ return;
+ }
+
+ CMStringA steamIds;
+ for (int i = 0; i < searchResult.GetItemCount(); i++)
+ {
+ const SteamWebApi::SearchApi::SearchItem *item = searchResult.GetAt(i);
+ if (steamIds.IsEmpty())
+ steamIds.Append(item->GetSteamId());
+ else
+ steamIds.AppendFormat(",%s", item->GetSteamId());
+ }
+
+ SteamWebApi::FriendApi::Summaries summarues;
+ SteamWebApi::FriendApi::LoadSummaries(m_hNetlibUser, token, steamIds, &summarues);
+
+ if (!summarues.IsSuccess())
+ {
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_FAILED, (HANDLE)STEAM_SEARCH_BYNAME, 0);
+ return;
+ }
+
+ for (int i = 0; i < summarues.GetItemCount(); i++)
+ {
+ const SteamWebApi::FriendApi::Summary *contact = summarues.GetAt(i);
+
+ STEAM_SEARCH_RESULT ssr = { 0 };
+ ssr.hdr.cbSize = sizeof(STEAM_SEARCH_RESULT);
+ ssr.hdr.flags = PSR_TCHAR;
+
+ ssr.hdr.id = mir_a2u(contact->GetSteamId());
+ ssr.hdr.nick = mir_wstrdup(contact->GetNickname());
+
+ const wchar_t *realname = contact->GetRealname();
+ const wchar_t *p = wcschr(realname, ' ');
+ if (p == NULL)
+ ssr.hdr.firstName = mir_wstrdup(realname);
+ else
+ {
+ int length = p - realname;
+ ssr.hdr.firstName = (wchar_t*)mir_alloc(sizeof(wchar_t) * (length + 1));
+ wmemcpy(ssr.hdr.firstName, realname, length);
+ ssr.hdr.firstName[length] = '\0';
+ ssr.hdr.lastName = mir_wstrdup(p + 1);
+ }
+
+ ssr.contact = contact;
+
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, (HANDLE)STEAM_SEARCH_BYNAME, (LPARAM)&ssr);
+ }
+
+ ProtoBroadcastAck(NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, (HANDLE)STEAM_SEARCH_BYNAME, 0);
}
\ No newline at end of file diff --git a/protocols/Steam/src/steam_dialogs.cpp b/protocols/Steam/src/steam_dialogs.cpp index a03114f6c8..ad836d841a 100644 --- a/protocols/Steam/src/steam_dialogs.cpp +++ b/protocols/Steam/src/steam_dialogs.cpp @@ -167,8 +167,10 @@ INT_PTR CALLBACK CSteamProto::MainOptionsProc(HWND hwnd, UINT message, WPARAM wP switch(LOWORD(wParam))
{
case IDC_USERNAME:
+ if ((HWND)lParam == GetFocus())
{
- if ((HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ EnableWindow(GetDlgItem(hwnd, IDC_USERNAME), !proto->IsOnline());
+ if (HIWORD(wParam) != EN_CHANGE) return 0;
proto->delSetting("SteamID");
proto->delSetting("Cookies");
proto->delSetting("TokenSecret");
@@ -179,8 +181,10 @@ INT_PTR CALLBACK CSteamProto::MainOptionsProc(HWND hwnd, UINT message, WPARAM wP break;
case IDC_PASSWORD:
+ if ((HWND)lParam == GetFocus())
{
- if ((HIWORD(wParam) != EN_CHANGE || (HWND)lParam != GetFocus())) return 0;
+ EnableWindow(GetDlgItem(hwnd, IDC_PASSWORD), !proto->IsOnline());
+ if (HIWORD(wParam) != EN_CHANGE) return 0;
proto->delSetting("Cookie");
proto->delSetting("TokenSecret");
char password[128];
@@ -212,17 +216,17 @@ INT_PTR CALLBACK CSteamProto::MainOptionsProc(HWND hwnd, UINT message, WPARAM wP char password[128];
GetDlgItemTextA(hwnd, IDC_PASSWORD, password, SIZEOF(password));
proto->setString("Password", password);
+ }
- wchar_t groupName[128];
- GetDlgItemText(hwnd, IDC_GROUP, groupName, SIZEOF(groupName));
- if (lstrlen(groupName) > 0)
- {
- proto->setWString(NULL, "DefaultGroup", groupName);
- Clist_CreateGroup(0, groupName);
- }
- else
- proto->delSetting(NULL, "DefaultGroup");
+ wchar_t groupName[128];
+ GetDlgItemText(hwnd, IDC_GROUP, groupName, SIZEOF(groupName));
+ if (lstrlen(groupName) > 0)
+ {
+ proto->setWString(NULL, "DefaultGroup", groupName);
+ Clist_CreateGroup(0, groupName);
}
+ else
+ proto->delSetting(NULL, "DefaultGroup");
return TRUE;
}
diff --git a/protocols/Steam/src/steam_proto.cpp b/protocols/Steam/src/steam_proto.cpp index 2684818880..1a7f7f2b7b 100644 --- a/protocols/Steam/src/steam_proto.cpp +++ b/protocols/Steam/src/steam_proto.cpp @@ -27,6 +27,8 @@ CSteamProto::CSteamProto(const char* protoName, const TCHAR* userName) : sid.ptszDescription = LPGENT("Protocol icon");
sid.iDefaultIndex = -IDI_STEAM;
Skin_AddIcon(&sid);
+
+ SetAllContactsStatus(ID_STATUS_OFFLINE);
}
CSteamProto::~CSteamProto()
@@ -36,11 +38,11 @@ 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);*/
+ if (psr->cbSize != sizeof(STEAM_SEARCH_RESULT))
+ return 0;
- return 0;
+ STEAM_SEARCH_RESULT *ssr = (STEAM_SEARCH_RESULT*)psr;
+ return AddContact(ssr->contact);
}
MCONTACT __cdecl CSteamProto::AddToListByEvent(int flags, int iContact, HANDLE hDbEvent)
@@ -93,7 +95,7 @@ DWORD_PTR __cdecl CSteamProto:: GetCaps(int type, MCONTACT hContact) switch(type)
{
case PFLAGNUM_1:
- return PF1_IM | PF1_BASICSEARCH;
+ return PF1_IM | PF1_BASICSEARCH | PF1_SEARCHBYNAME;
case PFLAGNUM_2:
return PF2_ONLINE;
case PFLAG_UNIQUEIDTEXT:
@@ -124,7 +126,18 @@ HANDLE __cdecl CSteamProto::SearchByEmail(const TCHAR* email) HANDLE __cdecl CSteamProto::SearchByName(const TCHAR* nick, const TCHAR* firstName, const TCHAR* lastName)
{
- return 0;
+ if (!this->IsOnline())
+ return 0;
+
+ CMString keywords;
+ keywords.AppendFormat(L" %s", nick);
+ keywords.AppendFormat(L" %s", firstName);
+ keywords.AppendFormat(L" %s", lastName);
+ keywords.Trim();
+
+ ForkThread(&CSteamProto::SearchByNameThread, mir_wstrdup(keywords));
+
+ return (HANDLE)STEAM_SEARCH_BYNAME;
}
HWND __cdecl CSteamProto::SearchAdvanced( HWND owner ) { return 0; }
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 28ef2f853a..1e2bcdd6a6 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -24,6 +24,13 @@ struct SendMessageParam const char *text;
};
+struct STEAM_SEARCH_RESULT
+{
+ PROTOSEARCHRESULT hdr;
+ const SteamWebApi::FriendApi::Summary *contact;
+};
+
+
class CSteamProto : public PROTO<CSteamProto>
{
public:
@@ -97,9 +104,6 @@ protected: void __cdecl PollingThread(void*);
// account
- static WORD SteamToMirandaStatus(int state);
- static int MirandaToSteamState(int status);
-
bool IsOnline();
bool IsMe(const char *steamId);
void Authorize(SteamWebApi::AuthorizationApi::AuthResult *authResult);
@@ -111,10 +115,14 @@ protected: void SetContactStatus(MCONTACT hContact, WORD status);
void SetAllContactsStatus(WORD status);
- MCONTACT FindContact(const char *steamId);
- MCONTACT AddContact(const SteamWebApi::FriendApi::Friend &contact);
+ void UpdateContact(MCONTACT hContact, const SteamWebApi::FriendApi::Summary *contact);
+ void __cdecl UpdateContactsThread(void*);
+ MCONTACT FindContact(const char *steamId);
+ MCONTACT AddContact(const SteamWebApi::FriendApi::Summary *contact);
+
void __cdecl SearchByIdThread(void*);
+ void __cdecl SearchByNameThread(void*);
// messages
void __cdecl SendMessageThread(void*);
@@ -126,7 +134,13 @@ protected: INT_PTR __cdecl OnAccountManagerInit(WPARAM wParam, LPARAM lParam);
static int __cdecl OnOptionsInit(void *obj, WPARAM wParam, LPARAM lParam);
- //options
+ // utils
+ static WORD SteamToMirandaStatus(int state);
+ static int MirandaToSteamState(int status);
+
+ static int RsaEncrypt(const SteamWebApi::RsaKeyApi::RsaKey &rsaKey, const char *data, DWORD dataSize, BYTE *encrypted, DWORD &encryptedSize);
+
+ // options
static INT_PTR CALLBACK GuardProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK CaptchaProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK MainOptionsProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
diff --git a/protocols/Steam/src/steam_thread.cpp b/protocols/Steam/src/steam_thread.cpp index ef6cb813b0..a4adad5ba8 100644 --- a/protocols/Steam/src/steam_thread.cpp +++ b/protocols/Steam/src/steam_thread.cpp @@ -7,9 +7,10 @@ void CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 me if (!pollResult->IsSuccess())
return;
+ CMStringA updatedIds;
for (int i = 0; i < pollResult->GetItemCount(); i++)
{
- const SteamWebApi::PollApi::PoolItem *item = pollResult->operator[](i);
+ const SteamWebApi::PollApi::PoolItem *item = pollResult->GetAt(i);
switch (item->GetType())
{
case SteamWebApi::PollApi::POOL_TYPE_TYPING:
@@ -83,11 +84,19 @@ void CSteamProto::PollStatus(const char *token, const char *sessionId, UINT32 me SetContactStatus(hContact, status);
}
+
+ if (updatedIds.IsEmpty())
+ updatedIds.Append(steamId);
+ else
+ updatedIds.AppendFormat(",%s", steamId);
}
}
break;
}
}
+
+ if (!updatedIds.IsEmpty())
+ ForkThread(&CSteamProto::UpdateContactsThread, mir_strdup(updatedIds));
}
void CSteamProto::PollingThread(void*)
@@ -117,15 +126,22 @@ void CSteamProto::PollingThread(void*) }*/
if (!pollResult.IsSuccess())
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+
+ // token has expired
+ if (pollResult.GetStatus() == HTTP_STATUS_UNAUTHORIZED)
+ {
+ delSetting("TokenSecret");
+ delSetting("Cookie");
+ }
+
break;
+ }
messageId = pollResult.GetMessageId();
- }
-
- if (pollResult.IsSuccess())
setDword("MessageID", messageId);
- else
- SetStatus(ID_STATUS_OFFLINE);
+ }
m_hPollingThread = NULL;
debugLogA("CSteamProto::PollingThread: leaving");
diff --git a/protocols/Steam/src/steam_utils.cpp b/protocols/Steam/src/steam_utils.cpp new file mode 100644 index 0000000000..2f2caca443 --- /dev/null +++ b/protocols/Steam/src/steam_utils.cpp @@ -0,0 +1,134 @@ +#include "common.h"
+
+WORD CSteamProto::SteamToMirandaStatus(int state)
+{
+ switch (state)
+ {
+ case 0: //Offline
+ return ID_STATUS_OFFLINE;
+ case 2: //Busy
+ return ID_STATUS_DND;
+ case 3: //Away
+ return ID_STATUS_AWAY;
+ /*case 4: //Snoozing
+ prim = PURPLE_STATUS_EXTENDED_AWAY;
+ break;
+ case 5: //Looking to trade
+ return "trade";
+ case 6: //Looking to play
+ return "play";*/
+ //case 1: //Online
+ default:
+ return ID_STATUS_ONLINE;
+ }
+}
+
+int CSteamProto::MirandaToSteamState(int status)
+{
+ switch (status)
+ {
+ case ID_STATUS_OFFLINE:
+ return 0; //Offline
+ case ID_STATUS_DND:
+ return 2; //Busy
+ case ID_STATUS_AWAY:
+ return 3; //Away
+ /*case 4: //Snoozing
+ prim = PURPLE_STATUS_EXTENDED_AWAY;
+ break;
+ case 5: //Looking to trade
+ return "trade";
+ case 6: //Looking to play
+ return "play";*/
+ //case 1: //Online
+ default:
+ return ID_STATUS_ONLINE;
+ }
+}
+
+int CSteamProto::RsaEncrypt(const SteamWebApi::RsaKeyApi::RsaKey &rsaKey, const char *data, DWORD dataSize, BYTE *encryptedData, DWORD &encryptedSize)
+{
+ 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))
+ return GetLastError();
+
+ // allocate a new buffer.
+ BYTE *pbBuffer = (BYTE*)malloc(cbLen);
+ if (!CryptStringToBinaryA(pszModulus, cchModulus, CRYPT_STRING_HEX, pbBuffer, &cbLen, &dwSkip, &dwFlags))
+ return GetLastError();
+
+ // 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))
+ return GetLastError();
+
+ // 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))
+ return GetLastError();
+
+ // if data is not allocated just renurn size
+ if (encryptedData == NULL)
+ {
+ // get length of encrypted data
+ if (!CryptEncrypt(phKey, 0, TRUE, 0, NULL, &encryptedSize, dataSize))
+ return GetLastError();
+ return 0;
+ }
+
+ // encrypt password
+ memcpy(encryptedData, data, dataSize);
+ if (!CryptEncrypt(phKey, 0, TRUE, 0, encryptedData, &dataSize, encryptedSize))
+ return GetLastError();
+
+ // reverse byte array again
+ for (int i = 0; i < encryptedSize / 2; ++i)
+ {
+ BYTE temp = encryptedData[encryptedSize - i - 1];
+ encryptedData[encryptedSize - i - 1] = encryptedData[i];
+ encryptedData[i] = temp;
+ }
+
+ free(pKeyBlob);
+ CryptDestroyKey(phKey);
+
+ free(pbBuffer);
+ CryptReleaseContext(hCSP, 0);
+
+ return 0;
+}
\ No newline at end of file |