summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorAlexander Lantsev <aunsane@gmail.com>2015-03-15 11:20:05 +0000
committerAlexander Lantsev <aunsane@gmail.com>2015-03-15 11:20:05 +0000
commit641c67a9d552b07664308c2ae3384cc95a75a2d0 (patch)
treeb9e29c5bf201211065b912bb2048143152c82201 /protocols
parent108bb117b2a796e8a99d7add61f304730b9ecadb (diff)
Steam:
- added support for templated url - fixed broken login - version bump git-svn-id: http://svn.miranda-ng.org/main/trunk@12408 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols')
-rw-r--r--protocols/Steam/src/Steam/authorization.h54
-rw-r--r--protocols/Steam/src/Steam/captcha.h4
-rw-r--r--protocols/Steam/src/Steam/friend_list.h6
-rw-r--r--protocols/Steam/src/Steam/pending.h18
-rw-r--r--protocols/Steam/src/Steam/rsa_key.h2
-rw-r--r--protocols/Steam/src/Steam/session.h50
-rw-r--r--protocols/Steam/src/Steam/steam.h130
-rw-r--r--protocols/Steam/src/steam_account.cpp527
-rw-r--r--protocols/Steam/src/steam_pooling.cpp6
-rw-r--r--protocols/Steam/src/steam_proto.h681
-rw-r--r--protocols/Steam/src/steam_queue.cpp11
-rw-r--r--protocols/Steam/src/version.h2
12 files changed, 750 insertions, 741 deletions
diff --git a/protocols/Steam/src/Steam/authorization.h b/protocols/Steam/src/Steam/authorization.h
index 194a5dee36..e72eef1a11 100644
--- a/protocols/Steam/src/Steam/authorization.h
+++ b/protocols/Steam/src/Steam/authorization.h
@@ -5,49 +5,55 @@ namespace SteamWebApi
{
class AuthorizationRequest : public HttpsPostRequest
{
- void InitData(const char *username, const char *password, const char *timestamp, const char *guardId = "-1", const char *guardCode = "", const char *captchaId = "-1", const char *captchaText = "")
+ public:
+ AuthorizationRequest(const char *username, const char *password, const char *timestamp) :
+ HttpsPostRequest(STEAM_WEB_URL "/mobilelogin/dologin")
{
+ flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
+
char data[1024];
mir_snprintf(data, SIZEOF(data),
- "username=%s&password=%s&emailsteamid=%s&emailauth=%s&captchagid=%s&captcha_text=%s&rsatimestamp=%s&donotcache=%ld&remember_login=true&oauth_client_id=DE45CD61&oauth_scope=read_profile write_profile read_client write_client",
- username,
+ "username=%s&password=%s&oauth_client_id=3638BFB1&oauth_scope=read_profile write_profile read_client write_client&captchagid=-1&rsatimestamp=%s",
+ ptrA(mir_urlEncode(username)),
ptrA(mir_urlEncode(password)),
- guardId,
- guardCode,
- captchaId,
- ptrA(mir_urlEncode(captchaText)),
- timestamp,
- time(NULL));
+ timestamp);
SetData(data, strlen(data));
}
- public:
- AuthorizationRequest(const char *username, const char *password, const char *timestamp) :
- HttpsPostRequest(STEAM_COM_URL "/mobilelogin/dologin")
+ AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *guardCode) :
+ HttpsPostRequest(STEAM_WEB_URL "/mobilelogin/dologin")
{
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
- InitData(username, password, timestamp);
- }
-
- AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *guardId, const char *guardCode) :
- HttpsPostRequest(STEAM_COM_URL "/mobilelogin/dologin")
- {
- flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
+ char data[1024];
+ mir_snprintf(data, SIZEOF(data),
+ "username=%s&password=%s&emailauth=%s&loginfriendlyname=MirandaNG&oauth_client_id=3638BFB1&oauth_scope=read_profile write_profile read_client write_client&captchagid=-1&rsatimestamp=%s",
+ ptrA(mir_urlEncode(username)),
+ ptrA(mir_urlEncode(password)),
+ guardCode,
+ timestamp);
- InitData(username, password, timestamp, guardId, guardCode);
+ SetData(data, strlen(data));
}
- AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *guardId, const char *guardCode, const char *captchaId, const char *captchaText) :
- HttpsPostRequest(STEAM_COM_URL "/mobilelogin/dologin")
+ AuthorizationRequest(const char *username, const char *password, const char *timestamp, const char *captchaId, const char *captchaText) :
+ HttpsPostRequest(STEAM_WEB_URL "/mobilelogin/dologin")
{
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
- InitData(username, password, timestamp, guardId, guardCode, captchaId, captchaText);
+ char data[1024];
+ mir_snprintf(data, SIZEOF(data),
+ "username=%s&password=%s&captchagid=%s&captcha_text=%s&oauth_client_id=3638BFB1&oauth_scope=read_profile write_profile read_client write_client&rsatimestamp=%s",
+ ptrA(mir_urlEncode(username)),
+ ptrA(mir_urlEncode(password)),
+ captchaId,
+ ptrA(mir_urlEncode(captchaText)),
+ timestamp);
+
+ SetData(data, strlen(data));
}
};
}
-
#endif //_STEAM_AUTHORIZATION_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/Steam/captcha.h b/protocols/Steam/src/Steam/captcha.h
index cb02fdda49..6ad01048ca 100644
--- a/protocols/Steam/src/Steam/captcha.h
+++ b/protocols/Steam/src/Steam/captcha.h
@@ -6,8 +6,8 @@ namespace SteamWebApi
class GetCaptchaRequest : public HttpGetRequest
{
public:
- GetCaptchaRequest(const char *url) :
- HttpGetRequest(url)
+ GetCaptchaRequest(const char *captchaId) :
+ HttpGetRequest(STEAM_WEB_URL "/public/captcha.php?gid=%s", captchaId)
{
flags = NLHRF_HTTP11 | NLHRF_NODUMP;
}
diff --git a/protocols/Steam/src/Steam/friend_list.h b/protocols/Steam/src/Steam/friend_list.h
index feed63f706..eccc3d1224 100644
--- a/protocols/Steam/src/Steam/friend_list.h
+++ b/protocols/Steam/src/Steam/friend_list.h
@@ -19,7 +19,7 @@ namespace SteamWebApi
{
public:
AddFriendRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/actions/AddFriendAjax")
+ HttpsPostRequest(STEAM_WEB_URL "/actions/AddFriendAjax")
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
@@ -42,7 +42,7 @@ namespace SteamWebApi
{
public:
BlockFriendRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/actions/BlockUserAjax")
+ HttpsPostRequest(STEAM_WEB_URL "/actions/BlockUserAjax")
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
@@ -65,7 +65,7 @@ namespace SteamWebApi
{
public:
RemoveFriendRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/actions/RemoveFriendAjax")
+ HttpsPostRequest(STEAM_WEB_URL "/actions/RemoveFriendAjax")
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
diff --git a/protocols/Steam/src/Steam/pending.h b/protocols/Steam/src/Steam/pending.h
index 5cdd85b885..68b86ad689 100644
--- a/protocols/Steam/src/Steam/pending.h
+++ b/protocols/Steam/src/Steam/pending.h
@@ -7,7 +7,7 @@ namespace SteamWebApi
{
public:
ApprovePendingRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/profiles/%s/home_process")
+ HttpsPostRequest(STEAM_WEB_URL "/profiles/%s/home_process", steamId)
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
@@ -15,10 +15,6 @@ namespace SteamWebApi
char cookie[MAX_PATH];
mir_snprintf(cookie, SIZEOF(cookie), "steamLogin=%s;sessionid=%s;forceMobile=1", login, sessionId);
- char url[MAX_PATH];
- mir_snprintf(url, SIZEOF(url), STEAM_COM_URL "/profiles/%s/home_process", steamId);
- this->url = url;
-
char data[MAX_PATH];
mir_snprintf(data, SIZEOF(data), "sessionID=%s&id=%s&perform=accept&action=approvePending&itype=friend&json=1&xml=0", sessionId, who);
@@ -31,7 +27,7 @@ namespace SteamWebApi
{
public:
IgnorePendingRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/profiles/%s/home_process")
+ HttpsPostRequest(STEAM_WEB_URL "/profiles/%s/home_process", steamId)
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
@@ -39,10 +35,6 @@ namespace SteamWebApi
char cookie[MAX_PATH];
mir_snprintf(cookie, SIZEOF(cookie), "steamLogin=%s;sessionid=%s;forceMobile=1", login, sessionId);
- char url[MAX_PATH];
- mir_snprintf(url, SIZEOF(url), STEAM_COM_URL "/profiles/%s/home_process", steamId);
- this->url = url;
-
char data[MAX_PATH];
mir_snprintf(data, SIZEOF(data), "sessionID=%s&id=%s&perform=ignore&action=approvePending&itype=friend&json=1&xml=0", sessionId, who);
@@ -55,7 +47,7 @@ namespace SteamWebApi
{
public:
BlockPendingRequest(const char *token, const char *sessionId, const char *steamId, const char *who) :
- HttpsPostRequest(STEAM_COM_URL "/profiles/%s/home_process")
+ HttpsPostRequest(STEAM_WEB_URL "/profiles/%s/home_process", steamId)
{
char login[MAX_PATH];
mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
@@ -63,10 +55,6 @@ namespace SteamWebApi
char cookie[MAX_PATH];
mir_snprintf(cookie, SIZEOF(cookie), "steamLogin=%s;sessionid=%s;forceMobile=1", login, sessionId);
- char url[MAX_PATH];
- mir_snprintf(url, SIZEOF(url), STEAM_COM_URL "/profiles/%s/home_process", steamId);
- this->url = url;
-
char data[MAX_PATH];
mir_snprintf(data, SIZEOF(data), "sessionID=%s&id=%s&perform=block&action=approvePending&itype=friend&json=1&xml=0", sessionId, who);
diff --git a/protocols/Steam/src/Steam/rsa_key.h b/protocols/Steam/src/Steam/rsa_key.h
index c4f9efc72d..be7d7ac79c 100644
--- a/protocols/Steam/src/Steam/rsa_key.h
+++ b/protocols/Steam/src/Steam/rsa_key.h
@@ -7,7 +7,7 @@ namespace SteamWebApi
{
public:
RsaKeyRequest(const char *username) :
- HttpsGetRequest(STEAM_COM_URL "/mobilelogin/getrsakey")
+ HttpsGetRequest(STEAM_WEB_URL "/mobilelogin/getrsakey")
{
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
diff --git a/protocols/Steam/src/Steam/session.h b/protocols/Steam/src/Steam/session.h
index a5fd950e1d..ea42cc77c4 100644
--- a/protocols/Steam/src/Steam/session.h
+++ b/protocols/Steam/src/Steam/session.h
@@ -3,59 +3,11 @@
namespace SteamWebApi
{
- //class SessionApi : public BaseApi
- //{
- //public:
- // class SessionId : public Result
- // {
- // friend SessionApi;
-
- // private:
- // std::string sessionid;
-
- // public:
-
- // const char *GetSessionId() { return sessionid.c_str(); }
- // };
-
- // static void GetSessionId(HANDLE hConnection, const char *token, const char *steamId, SessionId *sessionId)
- // {
- // sessionId->success = false;
-
- // char login[MAX_PATH];
- // mir_snprintf(login, SIZEOF(login), "%s||oauth:%s", steamId, token);
-
- // char cookie[MAX_PATH];
- // mir_snprintf(cookie, SIZEOF(cookie), "steamLogin=%s", ptrA(mir_urlEncode(login)));
-
- // SecureHttpGetRequest request(hConnection, STEAM_COM_URL "/mobilesettings/GetManifest/v0001");
- // request.AddHeader("Cookie", cookie);
-
- // mir_ptr<NETLIBHTTPREQUEST> response(request.Send());
- // if (!response)
- // return;
-
- // for (int i = 0; i < response->headersCount; i++)
- // {
- // if (lstrcmpiA(response->headers[i].szName, "Set-Cookie"))
- // continue;
-
- // std::string cookies = response->headers[i].szValue;
- // size_t start = cookies.find("sessionid=") + 10;
- // size_t end = cookies.substr(start).find(';');
- // sessionId->sessionid = cookies.substr(start, end - start + 10);
- // break;
- // }
-
- // sessionId->success = true;
- // }
- //};
-
class GetSessionRequest : public HttpsPostRequest
{
public:
GetSessionRequest(const char *token, const char *steamId, const char *cookie) :
- HttpsPostRequest(STEAM_COM_URL "/mobileloginsucceeded")
+ HttpsPostRequest(STEAM_WEB_URL "/mobileloginsucceeded")
{
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP;
diff --git a/protocols/Steam/src/Steam/steam.h b/protocols/Steam/src/Steam/steam.h
index c32da7e92a..a2a373a3d3 100644
--- a/protocols/Steam/src/Steam/steam.h
+++ b/protocols/Steam/src/Steam/steam.h
@@ -4,33 +4,31 @@
namespace SteamWebApi
{
#define STEAM_API_URL "https://api.steampowered.com"
- #define STEAM_COM_URL "https://steamcommunity.com"
+ #define STEAM_WEB_URL "https://steamcommunity.com"
class HttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
{
- public:
- std::string url;
-
- HttpRequest(int type, LPCSTR url)
+ private:
+ CMStringA url;
+
+ protected:
+ HttpRequest()
{
cbSize = sizeof(NETLIBHTTPREQUEST);
- requestType = type;
- this->url = url;
- szUrl = (char*)this->url.c_str();
- timeout = 0;
- flags = NLHRF_HTTP11 | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT;
+ AddHeader("user-agent", "Steam 1.2.0 / iPhone");
}
- ~HttpRequest()
+ HttpRequest(int type, LPCSTR urlFormat, va_list args)
{
- for (int i = 0; i < headersCount; i++)
- {
- mir_free(headers[i].szName);
- mir_free(headers[i].szValue);
- }
- mir_free(headers);
- mir_free(pData);
+ this->HttpRequest::HttpRequest();
+
+ requestType = type;
+ //timeout = 0;
+ flags = NLHRF_HTTP11 | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT;
+
+ url.AppendFormatV(urlFormat, args);
+ szUrl = url.GetBuffer();
}
void AddHeader(LPCSTR szName, LPCSTR szValue)
@@ -41,20 +39,23 @@ namespace SteamWebApi
headersCount++;
}
- void AddParameter(LPCSTR szName, LPCSTR szValue)
+ void AddParameter(const char *fmt, ...)
{
- if (url.find('?') == -1)
- url.append("?").append(szName).append("=").append(szValue);
+ va_list args;
+ va_start(args, fmt);
+ if (url.Find('?') == -1)
+ url += '?';
else
- url.append("&").append(szName).append("=").append(szValue);
+ url += '&';
+ url.AppendFormatV(fmt, args);
+ va_end(args);
+
+ szUrl = url.GetBuffer();
}
- void AddParameter(LPCSTR szValue)
+ void AddParameter(LPCSTR name, LPCSTR value)
{
- if (url.find('?') == -1)
- url.append("?").append(szValue);
- else
- url.append("&").append(szValue);
+ AddParameter("%s=%s", name, value);
}
void SetData(const char *data, size_t size)
@@ -67,28 +68,76 @@ namespace SteamWebApi
memcpy(pData, data, size);
pData[size] = 0;
}
+
+ public:
+ HttpRequest(int type, LPCSTR urlFormat, ...)
+ {
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(type, urlFormat, args);
+ va_end(args);
+ }
+
+ ~HttpRequest()
+ {
+ for (int i = 0; i < headersCount; i++)
+ {
+ mir_free(headers[i].szName);
+ mir_free(headers[i].szValue);
+ }
+ mir_free(headers);
+ mir_free(pData);
+ }
+
+ NETLIBHTTPREQUEST * Send(HANDLE hConnection)
+ {
+ char message[1024];
+ mir_snprintf(message, SIZEOF(message), "Send request to %s", szUrl);
+ CallService(MS_NETLIB_LOG, (WPARAM)hConnection, (LPARAM)&message);
+
+ return (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)hConnection, (LPARAM)this);
+ }
};
class HttpGetRequest : public HttpRequest
{
public:
- HttpGetRequest(LPCSTR url) : HttpRequest(REQUEST_GET, url) { }
+ HttpGetRequest(LPCSTR urlFormat, ...) : HttpRequest()
+ {
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(REQUEST_GET, urlFormat, args);
+ va_end(args);
+ }
};
- /*class HttpPostRequest : public HttpRequest
+ class HttpPostRequest : public HttpRequest
{
public:
- HttpPostRequest(LPCSTR url) : HttpRequest(REQUEST_POST, url)
+ HttpPostRequest(LPCSTR urlFormat, ...) : HttpRequest()
{
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(REQUEST_POST, urlFormat, args);
+ va_end(args);
+
AddHeader("Content-Type", "application/x-www-form-urlencoded");
}
- };*/
+ };
class HttpsRequest : public HttpRequest
{
+ protected:
+ HttpsRequest() : HttpRequest() { }
+
public:
- HttpsRequest(int type, LPCSTR url) : HttpRequest(type, url)
+ HttpsRequest(int type, LPCSTR urlFormat, ...) : HttpRequest()
{
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(type, urlFormat, args);
+ va_end(args);
+
flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT;
}
};
@@ -96,15 +145,26 @@ namespace SteamWebApi
class HttpsGetRequest : public HttpsRequest
{
public:
- HttpsGetRequest(LPCSTR url) : HttpsRequest(REQUEST_GET, url) { }
+ HttpsGetRequest(LPCSTR urlFormat, ...) : HttpsRequest()
+ {
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(REQUEST_GET, urlFormat, args);
+ va_end(args);
+ }
};
class HttpsPostRequest : public HttpsRequest
{
public:
- HttpsPostRequest(LPCSTR url) : HttpsRequest(REQUEST_POST, url)
+ HttpsPostRequest(LPCSTR urlFormat, ...) : HttpsRequest()
{
- AddHeader("Content-Type", "application/x-www-form-urlencoded");
+ va_list args;
+ va_start(args, urlFormat);
+ this->HttpRequest::HttpRequest(REQUEST_POST, urlFormat, args);
+ va_end(args);
+
+ AddHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
}
};
}
diff --git a/protocols/Steam/src/steam_account.cpp b/protocols/Steam/src/steam_account.cpp
index 7e16e5b850..94b26e384d 100644
--- a/protocols/Steam/src/steam_account.cpp
+++ b/protocols/Steam/src/steam_account.cpp
@@ -1,263 +1,266 @@
-#include "common.h"
-
-bool CSteamProto::IsOnline()
-{
- 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::OnGotRsaKey(const NETLIBHTTPREQUEST *response, void *arg)
-{
- if (response == NULL)
- return;
-
- // load rsa key parts
- JSONROOT root(response->pData);
- if (!root)
- return;
-
- JSONNODE *node = json_get(root, "success");
- if (!json_as_bool(node)) {
- return;
- }
-
- node = json_get(root, "publickey_mod");
- ptrA modulus(mir_u2a(ptrT(json_as_string(node))));
-
- // exponent "010001" is used as constant in CSteamProto::RsaEncrypt
- /*node = json_get(root, "publickey_exp");
- ptrA exponent(mir_u2a(ptrT(json_as_string(node))));*/
-
- node = json_get(root, "timestamp");
- ptrA timestamp(mir_u2a(ptrT(json_as_string(node))));
- setString("Timestamp", timestamp);
-
- // encrcrypt password
- ptrA base64RsaEncryptedPassword;
- ptrA password(getStringA("Password"));
-
- DWORD error = 0;
- DWORD encryptedSize = 0;
- DWORD passwordSize = (DWORD)strlen(password);
- if ((error = RsaEncrypt(modulus, password, NULL, encryptedSize)) != 0)
- {
- debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
- return;
- }
-
- BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
- if ((error = RsaEncrypt(modulus, password, encryptedPassword, encryptedSize)) != 0)
- {
- debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
- return;
- }
-
- base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
- mir_free(encryptedPassword);
-
- setString("EncryptedPassword", base64RsaEncryptedPassword);
-
- // run authorization request
- ptrA username(mir_urlEncode(ptrA(mir_utf8encodeW(getWStringA("Username")))));
-
- PushRequest(
- new SteamWebApi::AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp),
- &CSteamProto::OnAuthorization);
-}
-
-void CSteamProto::OnAuthorization(const NETLIBHTTPREQUEST *response, void *arg)
-{
- if (response == NULL) {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- JSONROOT root(response->pData);
-
- JSONNODE *node = json_get(root, "success");
- if (json_as_bool(node) == 0)
- {
- node = json_get(root, "message");
- ptrT message(json_as_string(node));
- if (!lstrcmpi(message, L"Incorrect login"))
- {
- ShowNotification(TranslateTS(message));
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- node = json_get(root, "emailauth_needed");
- if (json_as_bool(node) > 0)
- {
- node = json_get(root, "emailsteamid");
- ptrA guardId(mir_u2a(ptrT(json_as_string(node))));
-
- node = json_get(root, "emaildomain");
- ptrA emailDomain(mir_utf8encodeW(ptrT(json_as_string(node))));
-
- GuardParam guard;
- mir_strncpy(guard.domain, emailDomain, SIZEOF(guard.domain));
-
- if (DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_GUARD), NULL, CSteamProto::GuardProc, (LPARAM)&guard) != 1) {
- return;
- }
-
- ptrA username(mir_urlEncode(ptrA(mir_utf8encodeW(getWStringA("Username")))));
- ptrA base64RsaEncryptedPassword(getStringA("EncryptedPassword"));
- ptrA timestamp(getStringA("Timestamp"));
-
- PushRequest(
- new SteamWebApi::AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp, guardId, guard.code),
- &CSteamProto::OnAuthorization);
- }
-
- node = json_get(root, "captcha_needed");
- if (json_as_bool(node) > 0)
- {
- node = json_get(root, "captcha_gid");
- ptrA captchaId(mir_u2a(ptrT(json_as_string(node))));
-
- char url[MAX_PATH];
- mir_snprintf(url, SIZEOF(url), STEAM_COM_URL "/public/captcha.php?gid=%s", captchaId);
-
- SteamWebApi::GetCaptchaRequest *request = new SteamWebApi::GetCaptchaRequest(url);
- request->szUrl = (char*)request->url.c_str();
- NETLIBHTTPREQUEST *response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)request);
- delete request;
-
- CaptchaParam captcha = { 0 };
- captcha.size = response->dataLength;
- captcha.data = (BYTE*)mir_alloc(captcha.size);
- memcpy(captcha.data, response->pData, captcha.size);
-
- CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response);
-
- int res = DialogBoxParam(
- g_hInstance,
- MAKEINTRESOURCE(IDD_CAPTCHA),
- NULL,
- CSteamProto::CaptchaProc,
- (LPARAM)&captcha);
-
- mir_free(captcha.data);
-
- if (res != 1)
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- ptrA username(mir_urlEncode(ptrA(mir_utf8encodeW(getWStringA("Username")))));
- ptrA base64RsaEncryptedPassword(getStringA("EncryptedPassword"));
- ptrA timestamp(getStringA("Timestamp"));
-
- PushRequest(
- new SteamWebApi::AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp, "-1", "", captchaId, captcha.text),
- &CSteamProto::OnAuthorization);
- }
-
- return;
- }
-
- node = json_get(root, "login_complete");
- if (!json_as_bool(node))
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- node = json_get(root, "oauth");
- JSONROOT nroot(_T2A(ptrT(json_as_string(node))));
-
- node = json_get(nroot, "steamid");
- ptrA steamId(mir_u2a(ptrT(json_as_string(node))));
- setString("SteamID", steamId);
-
- node = json_get(nroot, "oauth_token");
- ptrA token(mir_u2a(ptrT(json_as_string(node))));
- setString("TokenSecret", token);
-
- node = json_get(nroot, "webcookie");
- ptrA cookie(mir_u2a(ptrT(json_as_string(node))));
-
- delSetting("Timestamp");
- delSetting("EncryptedPassword");
-
- PushRequest(
- new SteamWebApi::GetSessionRequest(token, steamId, cookie),
- &CSteamProto::OnGotSession);
-
- PushRequest(
- new SteamWebApi::LogonRequest(token),
- &CSteamProto::OnLoggedOn);
-}
-
-void CSteamProto::OnGotSession(const NETLIBHTTPREQUEST *response, void *arg)
-{
- if (response == NULL)
- return;
-
- for (int i = 0; i < response->headersCount; i++)
- {
- if (lstrcmpiA(response->headers[i].szName, "Set-Cookie"))
- continue;
-
- std::string cookies = response->headers[i].szValue;
- size_t start = cookies.find("sessionid=") + 10;
- size_t end = cookies.substr(start).find(';');
- std::string sessionId = cookies.substr(start, end - start + 10);
- setString("SessionID", sessionId.c_str());
- break;
- }
-}
-
-void CSteamProto::OnLoggedOn(const NETLIBHTTPREQUEST *response, void *arg)
-{
- if (response == NULL)
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- JSONROOT root(response->pData);
-
- JSONNODE *node = json_get(root, "error");
- ptrW error(json_as_string(node));
- if (lstrcmpi(error, L"OK")/* || response->resultCode == HTTP_STATUS_UNAUTHORIZED*/)
- {
- //delSetting("TokenSecret");
- //delSetting("Cookie");
-
- // set status to offline
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- node = json_get(root, "umqid");
- setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node)))));
-
- node = json_get(root, "message");
- setDword("MessageID", json_as_int(node));
-
- // load contact list
- ptrA token(getStringA("TokenSecret"));
- ptrA steamId(getStringA("SteamID"));
-
- PushRequest(
- new SteamWebApi::GetFriendListRequest(token, steamId),
- &CSteamProto::OnGotFriendList);
-
- // start polling thread
- m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL);
-
- // go to online now
- ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus);
+#include "common.h"
+
+bool CSteamProto::IsOnline()
+{
+ 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::OnGotRsaKey(const NETLIBHTTPREQUEST *response, void *arg)
+{
+ if (response == NULL)
+ return;
+
+ // load rsa key parts
+ JSONROOT root(response->pData);
+ if (!root)
+ return;
+
+ JSONNODE *node = json_get(root, "success");
+ if (!json_as_bool(node)) {
+ return;
+ }
+
+ node = json_get(root, "publickey_mod");
+ ptrA modulus(mir_u2a(ptrT(json_as_string(node))));
+
+ // exponent "010001" is used as constant in CSteamProto::RsaEncrypt
+ /*node = json_get(root, "publickey_exp");
+ ptrA exponent(mir_u2a(ptrT(json_as_string(node))));*/
+
+ node = json_get(root, "timestamp");
+ ptrA timestamp(mir_u2a(ptrT(json_as_string(node))));
+ setString("Timestamp", timestamp);
+
+ // encrcrypt password
+ ptrA base64RsaEncryptedPassword;
+ ptrA password(getStringA("Password"));
+
+ DWORD error = 0;
+ DWORD encryptedSize = 0;
+ DWORD passwordSize = (DWORD)strlen(password);
+ if ((error = RsaEncrypt(modulus, password, NULL, encryptedSize)) != 0)
+ {
+ debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
+ return;
+ }
+
+ BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
+ if ((error = RsaEncrypt(modulus, password, encryptedPassword, encryptedSize)) != 0)
+ {
+ debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
+ return;
+ }
+
+ base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
+ mir_free(encryptedPassword);
+
+ //setString("EncryptedPassword", base64RsaEncryptedPassword);
+ PasswordParam *param = (PasswordParam*)mir_alloc(sizeof(PasswordParam));
+ strcpy(param->password, base64RsaEncryptedPassword);
+ strcpy(param->timestamp, timestamp);
+
+ // run authorization request
+ ptrA username(mir_utf8encodeW(getWStringA("Username")));
+
+ PushRequest(
+ new SteamWebApi::AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp),
+ &CSteamProto::OnAuthorization, param, ARG_NO_FREE);
+}
+
+void CSteamProto::OnAuthorization(const NETLIBHTTPREQUEST *response, void *arg)
+{
+ if (response == NULL) {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ JSONROOT root(response->pData);
+
+ JSONNODE *node = json_get(root, "success");
+ if (json_as_bool(node) == 0)
+ {
+ node = json_get(root, "message");
+ ptrT message(json_as_string(node));
+ if (!lstrcmpi(message, L"Incorrect login"))
+ {
+ ShowNotification(TranslateTS(message));
+ SetStatus(ID_STATUS_OFFLINE);
+ mir_free(arg);
+ return;
+ }
+
+ node = json_get(root, "emailauth_needed");
+ if (json_as_bool(node) > 0)
+ {
+ node = json_get(root, "emailsteamid");
+ ptrA guardId(mir_u2a(ptrT(json_as_string(node))));
+
+ node = json_get(root, "emaildomain");
+ ptrA emailDomain(mir_utf8encodeW(ptrT(json_as_string(node))));
+
+ GuardParam guard;
+ mir_strncpy(guard.domain, emailDomain, SIZEOF(guard.domain));
+
+ if (DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_GUARD), NULL, CSteamProto::GuardProc, (LPARAM)&guard) != IDOK)
+ return;
+
+ ptrA username(mir_utf8encodeW(getWStringA("Username")));
+ PasswordParam *param = (PasswordParam*)arg;
+
+ PushRequest(
+ new SteamWebApi::AuthorizationRequest(username, param->password, param->timestamp, guard.code),
+ &CSteamProto::OnAuthorization);
+ return;
+ }
+
+ node = json_get(root, "captcha_needed");
+ if (json_as_bool(node) > 0)
+ {
+ node = json_get(root, "captcha_gid");
+ ptrA captchaId(mir_u2a(ptrT(json_as_string(node))));
+
+ SteamWebApi::GetCaptchaRequest *request = new SteamWebApi::GetCaptchaRequest(captchaId);
+ NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser);
+ delete request;
+
+ CaptchaParam captcha = { 0 };
+ captcha.size = response->dataLength;
+ captcha.data = (BYTE*)mir_alloc(captcha.size);
+ memcpy(captcha.data, response->pData, captcha.size);
+
+ CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response);
+
+ int res = DialogBoxParam(
+ g_hInstance,
+ MAKEINTRESOURCE(IDD_CAPTCHA),
+ NULL,
+ CSteamProto::CaptchaProc,
+ (LPARAM)&captcha);
+
+ mir_free(captcha.data);
+
+ if (res != 1)
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ ptrA username(mir_utf8encodeW(getWStringA("Username")));
+ PasswordParam *param = (PasswordParam*)arg;
+
+ PushRequest(
+ new SteamWebApi::AuthorizationRequest(username, param->password, param->timestamp, captchaId, captcha.text),
+ &CSteamProto::OnAuthorization);
+ return;
+ }
+
+ SetStatus(ID_STATUS_OFFLINE);
+ mir_free(arg);
+ return;
+ }
+
+ mir_free(arg);
+
+ node = json_get(root, "login_complete");
+ if (!json_as_bool(node))
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ node = json_get(root, "oauth");
+ JSONROOT nroot(_T2A(ptrT(json_as_string(node))));
+
+ node = json_get(nroot, "steamid");
+ ptrA steamId(mir_u2a(ptrT(json_as_string(node))));
+ setString("SteamID", steamId);
+
+ node = json_get(nroot, "oauth_token");
+ ptrA token(mir_u2a(ptrT(json_as_string(node))));
+ setString("TokenSecret", token);
+
+ node = json_get(nroot, "webcookie");
+ ptrA cookie(mir_u2a(ptrT(json_as_string(node))));
+
+ delSetting("Timestamp");
+ delSetting("EncryptedPassword");
+
+ PushRequest(
+ new SteamWebApi::GetSessionRequest(token, steamId, cookie),
+ &CSteamProto::OnGotSession);
+
+ PushRequest(
+ new SteamWebApi::LogonRequest(token),
+ &CSteamProto::OnLoggedOn);
+}
+
+void CSteamProto::OnGotSession(const NETLIBHTTPREQUEST *response, void *arg)
+{
+ if(response == NULL)
+ return;
+
+ for (int i = 0; i < response->headersCount; i++)
+ {
+ if (lstrcmpiA(response->headers[i].szName, "Set-Cookie"))
+ continue;
+
+ std::string cookies = response->headers[i].szValue;
+ size_t start = cookies.find("sessionid=") + 10;
+ size_t end = cookies.substr(start).find(';');
+ std::string sessionId = cookies.substr(start, end - start + 10);
+ setString("SessionID", sessionId.c_str());
+ break;
+ }
+}
+
+void CSteamProto::OnLoggedOn(const NETLIBHTTPREQUEST *response, void *arg)
+{
+ if (response == NULL)
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ JSONROOT root(response->pData);
+
+ JSONNODE *node = json_get(root, "error");
+ ptrW error(json_as_string(node));
+ if (lstrcmpi(error, L"OK")/* || response->resultCode == HTTP_STATUS_UNAUTHORIZED*/)
+ {
+ //delSetting("TokenSecret");
+ //delSetting("Cookie");
+
+ // set status to offline
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ node = json_get(root, "umqid");
+ setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node)))));
+
+ node = json_get(root, "message");
+ setDword("MessageID", json_as_int(node));
+
+ // load contact list
+ ptrA token(getStringA("TokenSecret"));
+ ptrA steamId(getStringA("SteamID"));
+
+ PushRequest(
+ new SteamWebApi::GetFriendListRequest(token, steamId),
+ &CSteamProto::OnGotFriendList);
+
+ // start polling thread
+ m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL);
+
+ // go to online now
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus);
} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_pooling.cpp b/protocols/Steam/src/steam_pooling.cpp
index 7097cc0dff..1bf9f8314e 100644
--- a/protocols/Steam/src/steam_pooling.cpp
+++ b/protocols/Steam/src/steam_pooling.cpp
@@ -178,10 +178,8 @@ void CSteamProto::PollingThread(void*)
while (!isTerminated && !breaked && errors < POLLING_ERRORS_LIMIT)
{
SteamWebApi::PollRequest *request = new SteamWebApi::PollRequest(token, umqId, messageId, IdleSeconds());
- debugLogA("CSteamProto::PollingThread: %s", request->szUrl);
- request->szUrl = (char*)request->url.c_str();
- request->nlc = m_pollingConnection;
- NETLIBHTTPREQUEST *response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)request);
+ //request->nlc = m_pollingConnection;
+ NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser);
delete request;
if (response == NULL || response->resultCode != HTTP_STATUS_OK)
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h
index 6ee5b79a8a..514410caea 100644
--- a/protocols/Steam/src/steam_proto.h
+++ b/protocols/Steam/src/steam_proto.h
@@ -1,338 +1,345 @@
-#ifndef _STEAM_PROTO_H_
-#define _STEAM_PROTO_H_
-
-#define STEAM_SEARCH_BYID 1001
-#define STEAM_SEARCH_BYNAME 1002
-#define STEAM_TYPING_TIME 10
-
-struct GuardParam
-{
- char code[10];
- char domain[32];
-};
-
-struct CaptchaParam
-{
- BYTE *data;
- size_t size;
- char text[10];
-};
-
-struct SendAuthParam
-{
- MCONTACT hContact;
- HANDLE hAuth;
-};
-
-struct SendMessageParam
-{
- MCONTACT hContact;
- HANDLE hMessage;
- const char *msg;
- int flags;
-};
-
-struct STEAM_SEARCH_RESULT
-{
- PROTOSEARCHRESULT hdr;
- JSONNODE *data;
-};
-
-enum
-{
- CMI_AUTH_REQUEST,
- //CMI_AUTH_GRANT,
- //CMI_AUTH_REVOKE,
- CMI_BLOCK,
- CMI_JOIN_GAME,
- SMI_BLOCKED_LIST,
- CMI_MAX // this item shall be the last one
-};
-
-enum HTTP_STATUS
-{
- HTTP_STATUS_NONE = 0,
- HTTP_STATUS_OK = 200,
- HTTP_STATUS_FOUND = 302,
- HTTP_STATUS_BAD_REQUEST = 400,
- HTTP_STATUS_UNAUTHORIZED = 401,
- HTTP_STATUS_FORBIDDEN = 403,
- HTTP_STATUS_NOT_FOUND = 404,
- HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
- HTTP_STATUS_TOO_MANY_REQUESTS = 429,
- HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
- HTTP_STATUS_INSUFICIENTE_STORAGE = 507
-};
-
-enum ARG_FREE_TYPE
-{
- ARG_NO_FREE,
- ARG_MIR_FREE
-};
-
-typedef void (CSteamProto::*RESPONSE)(const NETLIBHTTPREQUEST *response, void *arg);
-
-struct QueueItem
-{
- SteamWebApi::HttpRequest *request;
- void *arg;
- ARG_FREE_TYPE arg_free_type;
- RESPONSE responseCallback;
- //RESPONSE responseFailedCallback;
-
- QueueItem(SteamWebApi::HttpRequest *request) :
- request(request), arg(NULL), responseCallback(NULL)/*, responseFailedCallback(NULL)*/ { }
-
- QueueItem(SteamWebApi::HttpRequest *request, RESPONSE response) :
- request(request), arg(NULL), responseCallback(response)/*, responseFailedCallback(NULL)*/ { }
-
- //QueueItem(SteamWebApi::HttpRequest *request, RESPONSE response, RESPONSE responseFailedCallback) :
- // request(request), arg(NULL), responseCallback(response), responseFailedCallback(responseFailedCallback) { }
-
- ~QueueItem() {
- // Free request
- delete request;
-
- // Free argument
- switch (arg_free_type)
- {
- case ARG_NO_FREE:
- break;
- case ARG_MIR_FREE:
- mir_free(arg);
- default:
- break;
- }
-
- responseCallback = NULL;
- //responseFailedCallback = NULL;
- }
-};
-
-class CSteamProto : public PROTO<CSteamProto>
-{
-public:
- // PROTO_INTERFACE
- CSteamProto(const char *protoName, const wchar_t *userName);
- ~CSteamProto();
-
- // PROTO_INTERFACE
- virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT *psr);
- virtual MCONTACT __cdecl AddToListByEvent(int flags, int iContact, MEVENT hDbEvent);
-
- virtual int __cdecl Authorize(MEVENT hDbEvent);
- virtual int __cdecl AuthDeny(MEVENT hDbEvent, const TCHAR *szReason);
- virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT *);
- virtual int __cdecl AuthRequest(MCONTACT hContact, const TCHAR * szMessage);
-
- virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const TCHAR* szPath);
- virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer);
- virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const TCHAR* szReason);
- virtual int __cdecl FileResume(HANDLE hTransfer, int *action, const TCHAR** szFilename);
-
- virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
- virtual int __cdecl GetInfo(MCONTACT hContact, int infoType);
-
- virtual HANDLE __cdecl SearchBasic(const TCHAR *id);
- virtual HANDLE __cdecl SearchByEmail(const TCHAR *email);
- virtual HANDLE __cdecl SearchByName(const TCHAR *nick, const TCHAR *firstName, const TCHAR *lastName);
- virtual HWND __cdecl SearchAdvanced(HWND owner);
- virtual HWND __cdecl CreateExtendedSearchUI(HWND owner);
-
- virtual int __cdecl RecvContacts(MCONTACT hContact, PROTORECVEVENT*);
- virtual int __cdecl RecvFile(MCONTACT hContact, PROTORECVFILET*);
- virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*);
- virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*);
-
- virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList);
- virtual HANDLE __cdecl SendFile(MCONTACT hContact, const TCHAR* szDescription, TCHAR** ppszFiles);
- virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg);
- virtual int __cdecl SendUrl(MCONTACT hContact, int flags, const char* url);
-
- virtual int __cdecl SetApparentMode(MCONTACT hContact, int mode);
- virtual int __cdecl SetStatus(int iNewStatus);
-
- virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact);
- virtual int __cdecl RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt);
- virtual int __cdecl SetAwayMsg(int m_iStatus, const TCHAR* msg);
-
- virtual int __cdecl UserIsTyping(MCONTACT hContact, int type);
-
- virtual int __cdecl OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam);
-
- // instances
- static CSteamProto* InitProtoInstance(const char* protoName, const wchar_t* userName);
- static int UninitProtoInstance(CSteamProto* ppro);
-
- static CSteamProto* GetContactProtoInstance(MCONTACT hContact);
- static void UninitProtoInstances();
-
- // menus
- static void InitMenus();
- static void UninitMenus();
-
-protected:
- bool isTerminated;
- time_t m_idleTS;
- HANDLE m_evRequestsQueue, m_hQueueThread;
- HANDLE m_pollingConnection, m_hPollingThread;
- ULONG hAuthProcess;
- ULONG hMessageProcess;
- CRITICAL_SECTION contact_search_lock;
- CRITICAL_SECTION requests_queue_lock;
- CRITICAL_SECTION set_status_lock;
- LIST<QueueItem> requestsQueue;
-
- // instances
- static LIST<CSteamProto> InstanceList;
- static int CompareProtos(const CSteamProto *p1, const CSteamProto *p2);
-
- // queue
- void InitQueue();
- void UninitQueue();
-
- void StartQueue();
- void StopQueue();
-
- void PushRequest(SteamWebApi::HttpRequest *request);
- void PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response);
- void PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response, void *arg, ARG_FREE_TYPE arg_free_type);
-
- void ExecuteRequest(QueueItem *requestItem);
-
- void __cdecl SendMsgThread(void*);
- void __cdecl QueueThread(void*);
-
- // pooling thread
- void ParsePollData(JSONNODE *data);
- void __cdecl PollingThread(void*);
-
- // account
- bool IsOnline();
- bool IsMe(const char *steamId);
-
- void OnGotRsaKey(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnAuthorization(const NETLIBHTTPREQUEST *response, void *arg);
- void OnGotSession(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnLoggedOn(const NETLIBHTTPREQUEST *response, void *arg);
-
- // contacts
- void SetContactStatus(MCONTACT hContact, WORD status);
- void SetAllContactsStatus(WORD status);
-
- MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
-
- void UpdateContact(MCONTACT hContact, JSONNODE *data);
- void ProcessContact(std::map<std::string, JSONNODE*>::iterator *it, MCONTACT hContact);
-
- void ContactIsRemoved(MCONTACT hContact);
- void ContactIsFriend(MCONTACT hContact);
- void ContactIsIgnored(MCONTACT hContact);
-
- MCONTACT FindContact(const char *steamId);
- MCONTACT AddContact(const char *steamId, bool isTemporary = false);
-
- void OnGotFriendList(const NETLIBHTTPREQUEST *response, void *arg);
- void OnGotBlockList(const NETLIBHTTPREQUEST *response, void *arg);
- void OnGotUserSummaries(const NETLIBHTTPREQUEST *response, void *arg);
- void OnGotAvatar(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnFriendAdded(const NETLIBHTTPREQUEST *response, void *arg);
- void OnFriendBlocked(const NETLIBHTTPREQUEST *response, void *arg);
- void OnFriendRemoved(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnAuthRequested(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnPendingApproved(const NETLIBHTTPREQUEST *response, void *arg);
- void OnPendingIgnoreded(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnSearchByIdEnded(const NETLIBHTTPREQUEST *response, void *arg);
-
- void OnSearchByNameStarted(const NETLIBHTTPREQUEST *response, void *arg);
- void OnSearchByNameFinished(const NETLIBHTTPREQUEST *response, void *arg);
-
- // messages
- void OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg);
-
- // menus
- HGENMENU m_hMenuRoot;
- static HANDLE hChooserMenu;
- static HGENMENU contactMenuItems[CMI_MAX];
-
- int __cdecl AuthRequestCommand(WPARAM, LPARAM);
- int __cdecl BlockCommand(WPARAM, LPARAM);
- int __cdecl JoinToGameCommand(WPARAM, LPARAM);
-
- INT_PTR __cdecl OpenBlockListCommand(WPARAM, LPARAM);
-
- static INT_PTR MenuChooseService(WPARAM wParam, LPARAM lParam);
-
- static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
- int OnPrebuildContactMenu(WPARAM wParam, LPARAM);
-
- void OnInitStatusMenu();
-
- // avatars
- TCHAR* GetAvatarFilePath(MCONTACT hContact);
- bool GetDbAvatarInfo(PROTO_AVATAR_INFORMATIONT &pai);
- void CheckAvatarChange(MCONTACT hContact, std::string avatarUrl);
-
- INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM);
- INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM);
- INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM);
-
- // xstatuses
- INT_PTR __cdecl OnGetXStatusEx(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl OnGetXStatusIcon(WPARAM wParam, LPARAM lParam);
- INT_PTR __cdecl OnRequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam);
- HICON GetXStatusIcon(int status, UINT flags);
- int GetContactXStatus(MCONTACT hContact);
-
- // events
- int OnModulesLoaded(WPARAM, LPARAM);
- int OnPreShutdown(WPARAM, LPARAM);
- int __cdecl OnIdleChanged(WPARAM, LPARAM);
- INT_PTR __cdecl OnAccountManagerInit(WPARAM wParam, LPARAM lParam);
- static int __cdecl OnOptionsInit(void *obj, WPARAM wParam, LPARAM lParam);
-
- // utils
- static WORD SteamToMirandaStatus(int state);
- static int MirandaToSteamState(int status);
-
- static int RsaEncrypt(const char *pszModulus, const char *data, BYTE *encrypted, DWORD &encryptedSize);
-
- MEVENT AddDBEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob);
-
- static void CSteamProto::ShowNotification(const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
- static void CSteamProto::ShowNotification(const wchar_t *caption, const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
-
- // dialog procs
- 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);
- static LRESULT CALLBACK BlockListOptionsSubProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
- static INT_PTR CALLBACK BlockListOptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
-
- // helpers
- inline int IdleSeconds() {
- // Based on idle time we report Steam server will mark us as online/away/snooze
- switch (this->m_iStatus) {
- case ID_STATUS_AWAY:
- return STEAM_API_IDLEOUT_AWAY;
- case ID_STATUS_NA:
- return STEAM_API_IDLEOUT_SNOOZE;
- default:
- return 0;
- }
-
- // ... or we can report real idle info
- // return m_idleTS ? time(0) - m_idleTS : 0;
- }
-};
-
-int OnReloadIcons(WPARAM wParam, LPARAM lParam);
-void SetContactExtraIcon(MCONTACT hContact, int status);
-
+#ifndef _STEAM_PROTO_H_
+#define _STEAM_PROTO_H_
+
+#define STEAM_SEARCH_BYID 1001
+#define STEAM_SEARCH_BYNAME 1002
+#define STEAM_TYPING_TIME 10
+
+struct PasswordParam
+{
+ char password[513];
+ char timestamp[16];
+};
+
+
+struct GuardParam
+{
+ char code[10];
+ char domain[32];
+};
+
+struct CaptchaParam
+{
+ BYTE *data;
+ size_t size;
+ char text[10];
+};
+
+struct SendAuthParam
+{
+ MCONTACT hContact;
+ HANDLE hAuth;
+};
+
+struct SendMessageParam
+{
+ MCONTACT hContact;
+ HANDLE hMessage;
+ const char *msg;
+ int flags;
+};
+
+struct STEAM_SEARCH_RESULT
+{
+ PROTOSEARCHRESULT hdr;
+ JSONNODE *data;
+};
+
+enum
+{
+ CMI_AUTH_REQUEST,
+ //CMI_AUTH_GRANT,
+ //CMI_AUTH_REVOKE,
+ CMI_BLOCK,
+ CMI_JOIN_GAME,
+ SMI_BLOCKED_LIST,
+ CMI_MAX // this item shall be the last one
+};
+
+enum HTTP_STATUS
+{
+ HTTP_STATUS_NONE = 0,
+ HTTP_STATUS_OK = 200,
+ HTTP_STATUS_FOUND = 302,
+ HTTP_STATUS_BAD_REQUEST = 400,
+ HTTP_STATUS_UNAUTHORIZED = 401,
+ HTTP_STATUS_FORBIDDEN = 403,
+ HTTP_STATUS_NOT_FOUND = 404,
+ HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
+ HTTP_STATUS_TOO_MANY_REQUESTS = 429,
+ HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
+ HTTP_STATUS_INSUFICIENTE_STORAGE = 507
+};
+
+enum ARG_FREE_TYPE
+{
+ ARG_NO_FREE,
+ ARG_MIR_FREE
+};
+
+typedef void (CSteamProto::*RESPONSE)(const NETLIBHTTPREQUEST *response, void *arg);
+
+struct QueueItem
+{
+ SteamWebApi::HttpRequest *request;
+ void *arg;
+ ARG_FREE_TYPE arg_free_type;
+ RESPONSE responseCallback;
+ //RESPONSE responseFailedCallback;
+
+ QueueItem(SteamWebApi::HttpRequest *request) :
+ request(request), arg(NULL), responseCallback(NULL)/*, responseFailedCallback(NULL)*/ { }
+
+ QueueItem(SteamWebApi::HttpRequest *request, RESPONSE response) :
+ request(request), arg(NULL), responseCallback(response)/*, responseFailedCallback(NULL)*/ { }
+
+ //QueueItem(SteamWebApi::HttpRequest *request, RESPONSE response, RESPONSE responseFailedCallback) :
+ // request(request), arg(NULL), responseCallback(response), responseFailedCallback(responseFailedCallback) { }
+
+ ~QueueItem() {
+ // Free request
+ delete request;
+
+ // Free argument
+ switch (arg_free_type)
+ {
+ case ARG_NO_FREE:
+ break;
+ case ARG_MIR_FREE:
+ mir_free(arg);
+ default:
+ break;
+ }
+
+ responseCallback = NULL;
+ //responseFailedCallback = NULL;
+ }
+};
+
+class CSteamProto : public PROTO<CSteamProto>
+{
+public:
+ // PROTO_INTERFACE
+ CSteamProto(const char *protoName, const wchar_t *userName);
+ ~CSteamProto();
+
+ // PROTO_INTERFACE
+ virtual MCONTACT __cdecl AddToList(int flags, PROTOSEARCHRESULT *psr);
+ virtual MCONTACT __cdecl AddToListByEvent(int flags, int iContact, MEVENT hDbEvent);
+
+ virtual int __cdecl Authorize(MEVENT hDbEvent);
+ virtual int __cdecl AuthDeny(MEVENT hDbEvent, const TCHAR *szReason);
+ virtual int __cdecl AuthRecv(MCONTACT hContact, PROTORECVEVENT *);
+ virtual int __cdecl AuthRequest(MCONTACT hContact, const TCHAR * szMessage);
+
+ virtual HANDLE __cdecl FileAllow(MCONTACT hContact, HANDLE hTransfer, const TCHAR* szPath);
+ virtual int __cdecl FileCancel(MCONTACT hContact, HANDLE hTransfer);
+ virtual int __cdecl FileDeny(MCONTACT hContact, HANDLE hTransfer, const TCHAR* szReason);
+ virtual int __cdecl FileResume(HANDLE hTransfer, int *action, const TCHAR** szFilename);
+
+ virtual DWORD_PTR __cdecl GetCaps(int type, MCONTACT hContact = NULL);
+ virtual int __cdecl GetInfo(MCONTACT hContact, int infoType);
+
+ virtual HANDLE __cdecl SearchBasic(const TCHAR *id);
+ virtual HANDLE __cdecl SearchByEmail(const TCHAR *email);
+ virtual HANDLE __cdecl SearchByName(const TCHAR *nick, const TCHAR *firstName, const TCHAR *lastName);
+ virtual HWND __cdecl SearchAdvanced(HWND owner);
+ virtual HWND __cdecl CreateExtendedSearchUI(HWND owner);
+
+ virtual int __cdecl RecvContacts(MCONTACT hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvFile(MCONTACT hContact, PROTORECVFILET*);
+ virtual int __cdecl RecvMsg(MCONTACT hContact, PROTORECVEVENT*);
+ virtual int __cdecl RecvUrl(MCONTACT hContact, PROTORECVEVENT*);
+
+ virtual int __cdecl SendContacts(MCONTACT hContact, int flags, int nContacts, MCONTACT *hContactsList);
+ virtual HANDLE __cdecl SendFile(MCONTACT hContact, const TCHAR* szDescription, TCHAR** ppszFiles);
+ virtual int __cdecl SendMsg(MCONTACT hContact, int flags, const char* msg);
+ virtual int __cdecl SendUrl(MCONTACT hContact, int flags, const char* url);
+
+ virtual int __cdecl SetApparentMode(MCONTACT hContact, int mode);
+ virtual int __cdecl SetStatus(int iNewStatus);
+
+ virtual HANDLE __cdecl GetAwayMsg(MCONTACT hContact);
+ virtual int __cdecl RecvAwayMsg(MCONTACT hContact, int mode, PROTORECVEVENT* evt);
+ virtual int __cdecl SetAwayMsg(int m_iStatus, const TCHAR* msg);
+
+ virtual int __cdecl UserIsTyping(MCONTACT hContact, int type);
+
+ virtual int __cdecl OnEvent(PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam);
+
+ // instances
+ static CSteamProto* InitProtoInstance(const char* protoName, const wchar_t* userName);
+ static int UninitProtoInstance(CSteamProto* ppro);
+
+ static CSteamProto* GetContactProtoInstance(MCONTACT hContact);
+ static void UninitProtoInstances();
+
+ // menus
+ static void InitMenus();
+ static void UninitMenus();
+
+protected:
+ bool isTerminated;
+ time_t m_idleTS;
+ HANDLE m_evRequestsQueue, m_hQueueThread;
+ HANDLE m_pollingConnection, m_hPollingThread;
+ ULONG hAuthProcess;
+ ULONG hMessageProcess;
+ CRITICAL_SECTION contact_search_lock;
+ CRITICAL_SECTION requests_queue_lock;
+ CRITICAL_SECTION set_status_lock;
+ LIST<QueueItem> requestsQueue;
+
+ // instances
+ static LIST<CSteamProto> InstanceList;
+ static int CompareProtos(const CSteamProto *p1, const CSteamProto *p2);
+
+ // queue
+ void InitQueue();
+ void UninitQueue();
+
+ void StartQueue();
+ void StopQueue();
+
+ void PushRequest(SteamWebApi::HttpRequest *request);
+ void PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response);
+ void PushRequest(SteamWebApi::HttpRequest *request, RESPONSE response, void *arg, ARG_FREE_TYPE arg_free_type);
+
+ void ExecuteRequest(QueueItem *requestItem);
+
+ void __cdecl SendMsgThread(void*);
+ void __cdecl QueueThread(void*);
+
+ // pooling thread
+ void ParsePollData(JSONNODE *data);
+ void __cdecl PollingThread(void*);
+
+ // account
+ bool IsOnline();
+ bool IsMe(const char *steamId);
+
+ void OnGotRsaKey(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnAuthorization(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnGotSession(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnLoggedOn(const NETLIBHTTPREQUEST *response, void *arg);
+
+ // contacts
+ void SetContactStatus(MCONTACT hContact, WORD status);
+ void SetAllContactsStatus(WORD status);
+
+ MCONTACT GetContactFromAuthEvent(MEVENT hEvent);
+
+ void UpdateContact(MCONTACT hContact, JSONNODE *data);
+ void ProcessContact(std::map<std::string, JSONNODE*>::iterator *it, MCONTACT hContact);
+
+ void ContactIsRemoved(MCONTACT hContact);
+ void ContactIsFriend(MCONTACT hContact);
+ void ContactIsIgnored(MCONTACT hContact);
+
+ MCONTACT FindContact(const char *steamId);
+ MCONTACT AddContact(const char *steamId, bool isTemporary = false);
+
+ void OnGotFriendList(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnGotBlockList(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnGotUserSummaries(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnGotAvatar(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnFriendAdded(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnFriendBlocked(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnFriendRemoved(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnAuthRequested(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnPendingApproved(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnPendingIgnoreded(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnSearchByIdEnded(const NETLIBHTTPREQUEST *response, void *arg);
+
+ void OnSearchByNameStarted(const NETLIBHTTPREQUEST *response, void *arg);
+ void OnSearchByNameFinished(const NETLIBHTTPREQUEST *response, void *arg);
+
+ // messages
+ void OnMessageSent(const NETLIBHTTPREQUEST *response, void *arg);
+
+ // menus
+ HGENMENU m_hMenuRoot;
+ static HANDLE hChooserMenu;
+ static HGENMENU contactMenuItems[CMI_MAX];
+
+ int __cdecl AuthRequestCommand(WPARAM, LPARAM);
+ int __cdecl BlockCommand(WPARAM, LPARAM);
+ int __cdecl JoinToGameCommand(WPARAM, LPARAM);
+
+ INT_PTR __cdecl OpenBlockListCommand(WPARAM, LPARAM);
+
+ static INT_PTR MenuChooseService(WPARAM wParam, LPARAM lParam);
+
+ static int PrebuildContactMenu(WPARAM wParam, LPARAM lParam);
+ int OnPrebuildContactMenu(WPARAM wParam, LPARAM);
+
+ void OnInitStatusMenu();
+
+ // avatars
+ TCHAR* GetAvatarFilePath(MCONTACT hContact);
+ bool GetDbAvatarInfo(PROTO_AVATAR_INFORMATIONT &pai);
+ void CheckAvatarChange(MCONTACT hContact, std::string avatarUrl);
+
+ INT_PTR __cdecl GetAvatarInfo(WPARAM, LPARAM);
+ INT_PTR __cdecl GetAvatarCaps(WPARAM, LPARAM);
+ INT_PTR __cdecl GetMyAvatar(WPARAM, LPARAM);
+
+ // xstatuses
+ INT_PTR __cdecl OnGetXStatusEx(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl OnGetXStatusIcon(WPARAM wParam, LPARAM lParam);
+ INT_PTR __cdecl OnRequestAdvStatusIconIdx(WPARAM wParam, LPARAM lParam);
+ HICON GetXStatusIcon(int status, UINT flags);
+ int GetContactXStatus(MCONTACT hContact);
+
+ // events
+ int OnModulesLoaded(WPARAM, LPARAM);
+ int OnPreShutdown(WPARAM, LPARAM);
+ int __cdecl OnIdleChanged(WPARAM, LPARAM);
+ INT_PTR __cdecl OnAccountManagerInit(WPARAM wParam, LPARAM lParam);
+ static int __cdecl OnOptionsInit(void *obj, WPARAM wParam, LPARAM lParam);
+
+ // utils
+ static WORD SteamToMirandaStatus(int state);
+ static int MirandaToSteamState(int status);
+
+ static int RsaEncrypt(const char *pszModulus, const char *data, BYTE *encrypted, DWORD &encryptedSize);
+
+ MEVENT AddDBEvent(MCONTACT hContact, WORD type, DWORD timestamp, DWORD flags, DWORD cbBlob, PBYTE pBlob);
+
+ static void CSteamProto::ShowNotification(const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
+ static void CSteamProto::ShowNotification(const wchar_t *caption, const wchar_t *message, int flags = 0, MCONTACT hContact = NULL);
+
+ // dialog procs
+ 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);
+ static LRESULT CALLBACK BlockListOptionsSubProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static INT_PTR CALLBACK BlockListOptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+ // helpers
+ inline int IdleSeconds() {
+ // Based on idle time we report Steam server will mark us as online/away/snooze
+ switch (this->m_iStatus) {
+ case ID_STATUS_AWAY:
+ return STEAM_API_IDLEOUT_AWAY;
+ case ID_STATUS_NA:
+ return STEAM_API_IDLEOUT_SNOOZE;
+ default:
+ return 0;
+ }
+
+ // ... or we can report real idle info
+ // return m_idleTS ? time(0) - m_idleTS : 0;
+ }
+};
+
+int OnReloadIcons(WPARAM wParam, LPARAM lParam);
+void SetContactExtraIcon(MCONTACT hContact, int status);
+
#endif //_STEAM_PROTO_H_ \ No newline at end of file
diff --git a/protocols/Steam/src/steam_queue.cpp b/protocols/Steam/src/steam_queue.cpp
index ff61da24a7..6ef1aee6f7 100644
--- a/protocols/Steam/src/steam_queue.cpp
+++ b/protocols/Steam/src/steam_queue.cpp
@@ -63,9 +63,7 @@ void CSteamProto::StopQueue()
ptrA umqid(getStringA("UMQID"));
SteamWebApi::HttpRequest *request = new SteamWebApi::LogoffRequest(token, umqid);
- debugLogA("CSteamProto::StopQueue: %s", request->szUrl);
- request->szUrl = (char*)request->url.c_str();
- NETLIBHTTPREQUEST *response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)request);
+ NETLIBHTTPREQUEST *response = request->Send(m_hNetlibUser);
CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)response);
delete request;
@@ -113,10 +111,7 @@ void CSteamProto::ExecuteRequest(QueueItem *item)
return;
}
- debugLogA("CSteamProto::ExecuteRequest: %s", item->request->szUrl);
-
- item->request->szUrl = (char*)item->request->url.c_str();
- NETLIBHTTPREQUEST *response = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)item->request);
+ NETLIBHTTPREQUEST *response = item->request->Send(m_hNetlibUser);
if (item->responseCallback != NULL)
(this->*(item->responseCallback))(response, item->arg);
@@ -128,7 +123,7 @@ void CSteamProto::ExecuteRequest(QueueItem *item)
}
/*else if (requestItem->responseFailedCallback != NULL)
{
- (this->*(requestItem->responseFailedCallback))(response);
+ (this->*(requestItem->responseFailedCallback))(response);
}*/
delete item;
diff --git a/protocols/Steam/src/version.h b/protocols/Steam/src/version.h
index e33f795d5b..007f994986 100644
--- a/protocols/Steam/src/version.h
+++ b/protocols/Steam/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 11
#define __RELEASE_NUM 3
-#define __BUILD_NUM 0
+#define __BUILD_NUM 1
#include <stdver.h>