mirror of
https://github.com/spiffcode/hostile-takeover.git
synced 2025-12-16 12:08:36 +00:00
Client platform version can be retrieved live with /ids and is also recorded in the playerdetail module.
236 lines
6.3 KiB
C++
236 lines
6.3 KiB
C++
#include "game/loginhandler.h"
|
|
#include "game/simplerequest.h"
|
|
#include "game/serviceurls.h"
|
|
#include "game/httpservice.h"
|
|
#include "mpshared/messages.h"
|
|
#include "base/base64.h"
|
|
#include <ctype.h>
|
|
|
|
namespace wi {
|
|
|
|
const dword knGetTokenResultSuccess = 0;
|
|
const dword knGetTokenResultNoPassword = 1;
|
|
const dword knGetTokenResultTokenInvalid = 2;
|
|
const dword knGetTokenResultCreateRequestError = 3;
|
|
const dword knGetTokenResultServiceUnavailable = 4;
|
|
|
|
LoginHandler::LoginHandler() : loggedin_(false) {
|
|
InitFromGlobals();
|
|
}
|
|
|
|
LoginHandler::~LoginHandler() {
|
|
}
|
|
|
|
void LoginHandler::InitFromGlobals() {
|
|
strncpyz(token_, gszToken, sizeof(token_));
|
|
strncpyz(password_, gszPassword, sizeof(password_));
|
|
strncpyz(username_, gszUsername, sizeof(username_));
|
|
SetAnonymous(gfAnonymous);
|
|
}
|
|
|
|
void LoginHandler::SaveToGlobals() {
|
|
strncpyz(gszToken, token_, sizeof(gszToken));
|
|
strncpyz(gszPassword, password_, sizeof(gszPassword));
|
|
strncpyz(gszUsername, username_, sizeof(gszUsername));
|
|
gfAnonymous = anonymous_;
|
|
ggame.SavePreferences();
|
|
}
|
|
|
|
void LoginHandler::SetAnonymous(bool anonymous) {
|
|
anonymous_ = anonymous;
|
|
}
|
|
|
|
void LoginHandler::SetUsername(const char *username) {
|
|
strncpyz(username_, username, sizeof(username_));
|
|
}
|
|
|
|
void LoginHandler::SetPassword(const char *password) {
|
|
strncpyz(password_, password, sizeof(password_));
|
|
}
|
|
|
|
void LoginHandler::GetPlayerName(char *psz, int cb) {
|
|
if (anonymous_) {
|
|
if (gptra != NULL) {
|
|
strncpyz(psz, gptra->GetAnonymousUsername(), cb);
|
|
} else {
|
|
strncpyz(psz, "anonymous", cb);
|
|
}
|
|
} else {
|
|
strncpyz(psz, username_, cb);
|
|
}
|
|
}
|
|
|
|
dword LoginHandler::Login() {
|
|
if (gptra == NULL) {
|
|
return knLoginResultFail;
|
|
}
|
|
|
|
if (!anonymous_ && token_[0] == 0) {
|
|
switch (GetToken()) {
|
|
case knGetTokenResultSuccess:
|
|
break;
|
|
case knGetTokenResultNoPassword:
|
|
return knLoginResultNoPassword;
|
|
case knGetTokenResultTokenInvalid:
|
|
case knGetTokenResultCreateRequestError:
|
|
return knLoginResultFail;
|
|
case knGetTokenResultServiceUnavailable:
|
|
return knLoginResultAuthDown;
|
|
}
|
|
}
|
|
|
|
dword result = gptra->Login(username_, token_);
|
|
|
|
// If successful, return and keep the token
|
|
if (result == knLoginResultSuccess ||
|
|
result == knLoginResultAnonymousSuccess) {
|
|
loggedin_ = true;
|
|
SaveToGlobals();
|
|
return result;
|
|
}
|
|
|
|
// Otherwise don't save the token
|
|
token_[0] = 0;
|
|
|
|
// If token stale, try again otherwise return
|
|
if (result != knLoginResultStaleToken) {
|
|
return result;
|
|
}
|
|
|
|
// Get a new token
|
|
if (!GetToken()) {
|
|
switch (GetToken()) {
|
|
case knGetTokenResultSuccess:
|
|
break;
|
|
case knGetTokenResultNoPassword:
|
|
return knLoginResultNoPassword;
|
|
case knGetTokenResultTokenInvalid:
|
|
case knGetTokenResultCreateRequestError:
|
|
return knLoginResultFail;
|
|
case knGetTokenResultServiceUnavailable:
|
|
return knLoginResultAuthDown;
|
|
}
|
|
}
|
|
|
|
result = gptra->Login(username_, token_);
|
|
|
|
// If successful, return and keep the token
|
|
if (result == knLoginResultSuccess ||
|
|
result == knLoginResultAnonymousSuccess) {
|
|
loggedin_ = true;
|
|
SaveToGlobals();
|
|
return result;
|
|
}
|
|
|
|
// Otherwise don't save the token
|
|
token_[0] = 0;
|
|
|
|
// If this token is stale for some reason, there is a bug.
|
|
// Convert into "fail".
|
|
if (result == knLoginResultStaleToken) {
|
|
return knLoginResultFail;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
dword LoginHandler::SignOut() {
|
|
loggedin_ = false;
|
|
token_[0] = 0;
|
|
|
|
if (!anonymous_) {
|
|
// Sign out user - erase password, keep username
|
|
password_[0] = 0;
|
|
}
|
|
SaveToGlobals();
|
|
if (gptra == NULL) {
|
|
return knSignOutResultFail;
|
|
}
|
|
return gptra->SignOut();
|
|
}
|
|
|
|
dword LoginHandler::GetToken() {
|
|
// Wipe out the current token, if there is one
|
|
token_[0] = 0;
|
|
|
|
// Don't send a request for a token if the user has no password
|
|
if (password_[0] == 0) {
|
|
return knGetTokenResultNoPassword;
|
|
}
|
|
|
|
// Ask the authentication server for an auth token. Use https
|
|
// so ok to send password cleartext. Encode base64 to avoid
|
|
// url encoding parameters.
|
|
|
|
const char *s = base::Format::ToString("%s#%s", username_, password_);
|
|
char input[sizeof(username_) + sizeof(password_)];
|
|
strncpyz(input, s, sizeof(input));
|
|
int cchInput = (int)strlen(input);
|
|
input[strlen(username_)] = 0;
|
|
char output[(sizeof(username_) + sizeof(password_)) * 2];
|
|
int cb = base::base64encode((const byte *)input, cchInput, (byte *)output,
|
|
sizeof(output));
|
|
if (cb == -1) {
|
|
return knGetTokenResultCreateRequestError;
|
|
}
|
|
output[cb] = 0;
|
|
|
|
// Submit a simple blocking request to get the token
|
|
|
|
SimpleRequest req(gphttp);
|
|
std::string d = base::StringEncoder::QueryEncode(gszDeviceId);
|
|
std::string o(base::StringEncoder::QueryEncode(HostGetPlatformString()));
|
|
const char *url = base::Format::ToString("%s?a=%s&d=%s&o=%s", kszAuthUrl, output,
|
|
d.c_str(), o.c_str());
|
|
req.SetTimeout(60);
|
|
|
|
char result[kcbTokenMax];
|
|
if (!req.Get(url, result, sizeof(result))) {
|
|
return knGetTokenResultServiceUnavailable;
|
|
}
|
|
int cchResult = (int)strlen(result);
|
|
|
|
// Strip whitespace from the start and end.
|
|
char *start = result;
|
|
for (; start < &result[cchResult]; start++) {
|
|
if (!isspace(*start)) {
|
|
break;
|
|
}
|
|
}
|
|
char *end = &result[cchResult - 1];
|
|
for (; end > start; end--) {
|
|
if (!isspace(*end)) {
|
|
end++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (end <= start) {
|
|
return knGetTokenResultTokenInvalid;
|
|
}
|
|
strncpyz(token_, start, (int)(end - start + 1));
|
|
return knGetTokenResultSuccess;
|
|
}
|
|
|
|
bool LoginHandler::ShouldAttemptLogin() {
|
|
if (anonymous_) {
|
|
return true;
|
|
}
|
|
return username_[0] != 0 && password_[0] != 0;
|
|
}
|
|
|
|
const char *LoginHandler::StatsUsername() {
|
|
// Return the username to use for stats. Only return username if:
|
|
// 1. The user is not anonymous
|
|
// 2. It has been used to login successfully before
|
|
if (anonymous_) {
|
|
return "";
|
|
}
|
|
if (token_[0] == 0) {
|
|
return "";
|
|
}
|
|
return username_;
|
|
}
|
|
|
|
} // namespace wi
|