cMojangAPI: Added UUID-to-Name lookup.
Also fixed the bindings, now all functions are static-like.
This commit is contained in:
@@ -25,8 +25,10 @@ const int MAX_PER_QUERY = 100;
|
||||
|
||||
|
||||
|
||||
#define DEFAULT_NAME_TO_UUID_SERVER "api.mojang.com"
|
||||
#define DEFAULT_NAME_TO_UUID_ADDRESS "/profiles/minecraft"
|
||||
#define DEFAULT_NAME_TO_UUID_SERVER "api.mojang.com"
|
||||
#define DEFAULT_NAME_TO_UUID_ADDRESS "/profiles/minecraft"
|
||||
#define DEFAULT_UUID_TO_PROFILE_SERVER "sessionserver.mojang.com"
|
||||
#define DEFAULT_UUID_TO_PROFILE_ADDRESS "/session/minecraft/profile/%UUID%?unsigned=false"
|
||||
|
||||
|
||||
|
||||
@@ -96,12 +98,66 @@ static const AString & StarfieldCACert(void)
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cMojangAPI::sProfile:
|
||||
|
||||
cMojangAPI::sProfile::sProfile(
|
||||
const AString & a_PlayerName,
|
||||
const AString & a_UUID,
|
||||
const Json::Value & a_Properties,
|
||||
Int64 a_DateTime
|
||||
) :
|
||||
m_PlayerName(a_PlayerName),
|
||||
m_UUID(a_UUID),
|
||||
m_Textures(),
|
||||
m_TexturesSignature(),
|
||||
m_DateTime(a_DateTime)
|
||||
{
|
||||
/*
|
||||
Example a_Profile contents:
|
||||
"properties":
|
||||
[
|
||||
{
|
||||
"name": "textures",
|
||||
"value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19",
|
||||
"signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8="
|
||||
}
|
||||
]
|
||||
*/
|
||||
|
||||
// Parse the Textures and TexturesSignature from the Profile:
|
||||
if (!a_Properties.isArray())
|
||||
{
|
||||
// Properties is not a valid array, bail out
|
||||
return;
|
||||
}
|
||||
Json::UInt Size = a_Properties.size();
|
||||
for (Json::UInt i = 0; i < Size; i++)
|
||||
{
|
||||
const Json::Value & Prop = a_Properties[i];
|
||||
AString PropName = Prop.get("name", "").asString();
|
||||
if (PropName != "textures")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
m_Textures = Prop.get("value", "").asString();
|
||||
m_TexturesSignature = Prop.get("signature", "").asString();
|
||||
break;
|
||||
} // for i - Properties[]
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cMojangAPI:
|
||||
|
||||
cMojangAPI::cMojangAPI(void) :
|
||||
m_NameToUUIDServer(DEFAULT_NAME_TO_UUID_SERVER),
|
||||
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS)
|
||||
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
|
||||
m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
|
||||
m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -120,8 +176,10 @@ cMojangAPI::~cMojangAPI()
|
||||
|
||||
void cMojangAPI::Start(cIniFile & a_SettingsIni)
|
||||
{
|
||||
m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
|
||||
m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
|
||||
m_NameToUUIDServer = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDServer", DEFAULT_NAME_TO_UUID_SERVER);
|
||||
m_NameToUUIDAddress = a_SettingsIni.GetValueSet("MojangAPI", "NameToUUIDAddress", DEFAULT_NAME_TO_UUID_ADDRESS);
|
||||
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
|
||||
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
|
||||
LoadCachesFromDisk();
|
||||
}
|
||||
|
||||
@@ -135,7 +193,7 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
AString lcPlayerName(a_PlayerName);
|
||||
StrToLower(lcPlayerName);
|
||||
|
||||
// Request the cache to populate any names not yet contained:
|
||||
// Request the cache to query the name if not yet cached:
|
||||
if (!a_UseOnlyCached)
|
||||
{
|
||||
AStringVector PlayerNames;
|
||||
@@ -144,7 +202,8 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
}
|
||||
|
||||
// Retrieve from cache:
|
||||
cNameToUUIDMap::const_iterator itr = m_NameToUUID.find(lcPlayerName);
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
cProfileMap::const_iterator itr = m_NameToUUID.find(lcPlayerName);
|
||||
if (itr == m_NameToUUID.end())
|
||||
{
|
||||
// No UUID found
|
||||
@@ -157,6 +216,44 @@ AString cMojangAPI::GetUUIDFromPlayerName(const AString & a_PlayerName, bool a_U
|
||||
|
||||
|
||||
|
||||
AString cMojangAPI::GetPlayerNameFromUUID(const AString & a_UUID, bool a_UseOnlyCached)
|
||||
{
|
||||
// Normalize the UUID to lowercase short format that is used as the map key:
|
||||
AString UUID = StrToLower(MakeUUIDShort(a_UUID));
|
||||
|
||||
// Retrieve from caches:
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
cProfileMap::const_iterator itr = m_UUIDToProfile.find(UUID);
|
||||
if (itr != m_UUIDToProfile.end())
|
||||
{
|
||||
return itr->second.m_PlayerName;
|
||||
}
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
cProfileMap::const_iterator itr = m_UUIDToName.find(UUID);
|
||||
if (itr != m_UUIDToName.end())
|
||||
{
|
||||
return itr->second.m_PlayerName;
|
||||
}
|
||||
}
|
||||
|
||||
// Name not yet cached, request cache and retry:
|
||||
if (!a_UseOnlyCached)
|
||||
{
|
||||
CacheUUIDToProfile(UUID);
|
||||
return GetPlayerNameFromUUID(a_UUID, true);
|
||||
}
|
||||
|
||||
// No value found, none queried. Return an error:
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_PlayerNames, bool a_UseOnlyCached)
|
||||
{
|
||||
// Convert all playernames to lowercase:
|
||||
@@ -180,7 +277,7 @@ AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_Player
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (AStringVector::const_iterator itr = PlayerNames.begin(), end = PlayerNames.end(); itr != end; ++itr, ++idx)
|
||||
{
|
||||
cNameToUUIDMap::const_iterator itrN = m_NameToUUID.find(*itr);
|
||||
cProfileMap::const_iterator itrN = m_NameToUUID.find(*itr);
|
||||
if (itrN != m_NameToUUID.end())
|
||||
{
|
||||
res[idx] = itrN->second.m_UUID;
|
||||
@@ -196,10 +293,39 @@ AStringVector cMojangAPI::GetUUIDsFromPlayerNames(const AStringVector & a_Player
|
||||
void cMojangAPI::AddPlayerNameToUUIDMapping(const AString & a_PlayerName, const AString & a_UUID)
|
||||
{
|
||||
AString lcName(a_PlayerName);
|
||||
AString UUID = MakeUUIDShort(a_UUID);
|
||||
AString UUID = StrToLower(MakeUUIDShort(a_UUID));
|
||||
Int64 Now = time(NULL);
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(lcName)] = sUUIDRecord(a_PlayerName, UUID, Now);
|
||||
{
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(lcName)] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::AddPlayerProfile(const AString & a_PlayerName, const AString & a_UUID, const Json::Value & a_Properties)
|
||||
{
|
||||
AString lcName(a_PlayerName);
|
||||
AString UUID = StrToLower(MakeUUIDShort(a_UUID));
|
||||
Int64 Now = time(NULL);
|
||||
{
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(lcName)] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
m_UUIDToName[UUID] = sProfile(a_PlayerName, UUID, "", "", Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
m_UUIDToProfile[UUID] = sProfile(a_PlayerName, UUID, a_Properties, Now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -337,6 +463,7 @@ void cMojangAPI::LoadCachesFromDisk(void)
|
||||
// Open up the SQLite DB:
|
||||
SQLite::Database db("MojangAPI.sqlite", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
|
||||
|
||||
// Clean up old entries:
|
||||
{
|
||||
@@ -345,16 +472,40 @@ void cMojangAPI::LoadCachesFromDisk(void)
|
||||
stmt.bind(1, LimitDateTime);
|
||||
stmt.exec();
|
||||
}
|
||||
|
||||
// Retrieve all remaining entries::
|
||||
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
|
||||
while (stmt.executeStep())
|
||||
{
|
||||
AString PlayerName = stmt.getColumn(0);
|
||||
AString UUID = stmt.getColumn(1);
|
||||
Int64 DateTime = stmt.getColumn(2);
|
||||
AString lcPlayerName = PlayerName;
|
||||
m_NameToUUID[StrToLower(lcPlayerName)] = sUUIDRecord(PlayerName, UUID, DateTime);
|
||||
SQLite::Statement stmt(db, "DELETE FROM UUIDToProfile WHERE DateTime < ?");
|
||||
Int64 LimitDateTime = time(NULL) - MAX_AGE;
|
||||
stmt.bind(1, LimitDateTime);
|
||||
stmt.exec();
|
||||
}
|
||||
|
||||
// Retrieve all remaining entries:
|
||||
{
|
||||
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
|
||||
while (stmt.executeStep())
|
||||
{
|
||||
AString PlayerName = stmt.getColumn(0);
|
||||
AString UUID = stmt.getColumn(1);
|
||||
Int64 DateTime = stmt.getColumn(2);
|
||||
AString lcPlayerName = PlayerName;
|
||||
UUID = StrToLower(MakeUUIDShort(UUID));
|
||||
m_NameToUUID[StrToLower(lcPlayerName)] = sProfile(PlayerName, UUID, "", "", DateTime);
|
||||
m_UUIDToName[UUID] = sProfile(PlayerName, UUID, "", "", DateTime);
|
||||
}
|
||||
}
|
||||
{
|
||||
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, Textures, TexturesSignature, DateTime FROM UUIDToProfile");
|
||||
while (stmt.executeStep())
|
||||
{
|
||||
AString PlayerName = stmt.getColumn(0);
|
||||
AString UUID = stmt.getColumn(1);
|
||||
AString Textures = stmt.getColumn(2);
|
||||
AString TexturesSignature = stmt.getColumn(2);
|
||||
Int64 DateTime = stmt.getColumn(4);
|
||||
AString lcPlayerName = PlayerName;
|
||||
UUID = StrToLower(MakeUUIDShort(UUID));
|
||||
m_UUIDToProfile[StrToLower(lcPlayerName)] = sProfile(PlayerName, UUID, Textures, TexturesSignature, DateTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const SQLite::Exception & ex)
|
||||
@@ -374,26 +525,51 @@ void cMojangAPI::SaveCachesToDisk(void)
|
||||
// Open up the SQLite DB:
|
||||
SQLite::Database db("MojangAPI.sqlite", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
|
||||
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
|
||||
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
|
||||
|
||||
// Remove all entries:
|
||||
db.exec("DELETE FROM PlayerNameToUUID");
|
||||
db.exec("DELETE FROM UUIDToProfile");
|
||||
|
||||
// Save all cache entries:
|
||||
SQLite::Statement stmt(db, "INSERT INTO PlayerNameToUUID(PlayerName, UUID, DateTime) VALUES (?, ?, ?)");
|
||||
// Save all cache entries - m_PlayerNameToUUID:
|
||||
Int64 LimitDateTime = time(NULL) - MAX_AGE;
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (cNameToUUIDMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
SQLite::Statement stmt(db, "INSERT INTO PlayerNameToUUID(PlayerName, UUID, DateTime) VALUES (?, ?, ?)");
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
|
||||
{
|
||||
// This item is too old, do not save
|
||||
continue;
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
{
|
||||
// This item is too old, do not save
|
||||
continue;
|
||||
}
|
||||
stmt.bind(1, itr->second.m_PlayerName);
|
||||
stmt.bind(2, itr->second.m_UUID);
|
||||
stmt.bind(3, itr->second.m_DateTime);
|
||||
stmt.exec();
|
||||
stmt.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Save all cache entries - m_UUIDToProfile:
|
||||
{
|
||||
SQLite::Statement stmt(db, "INSERT INTO UUIDToProfile(UUID, PlayerName, Textures, TexturesSignature, DateTime) VALUES (?, ?, ?, ?, ?)");
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
|
||||
{
|
||||
if (itr->second.m_DateTime < LimitDateTime)
|
||||
{
|
||||
// This item is too old, do not save
|
||||
continue;
|
||||
}
|
||||
stmt.bind(1, itr->second.m_UUID);
|
||||
stmt.bind(2, itr->second.m_PlayerName);
|
||||
stmt.bind(3, itr->second.m_Textures);
|
||||
stmt.bind(4, itr->second.m_TexturesSignature);
|
||||
stmt.bind(5, itr->second.m_DateTime);
|
||||
stmt.exec();
|
||||
stmt.reset();
|
||||
}
|
||||
stmt.bind(1, itr->second.m_PlayerName);
|
||||
stmt.bind(2, itr->second.m_UUID);
|
||||
stmt.bind(3, itr->second.m_DateTime);
|
||||
stmt.exec();
|
||||
stmt.reset();
|
||||
}
|
||||
}
|
||||
catch (const SQLite::Exception & ex)
|
||||
@@ -487,22 +663,145 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
|
||||
// Store the returned results into cache:
|
||||
size_t JsonCount = root.size();
|
||||
Int64 Now = time(NULL);
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (size_t idx = 0; idx < JsonCount; ++idx)
|
||||
{
|
||||
Json::Value & Val = root[idx];
|
||||
AString JsonName = Val.get("name", "").asString();
|
||||
AString JsonUUID = MakeUUIDShort(Val.get("id", "").asString());
|
||||
if (JsonUUID.empty())
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
for (size_t idx = 0; idx < JsonCount; ++idx)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AString lcName = JsonName;
|
||||
m_NameToUUID[StrToLower(lcName)] = sUUIDRecord(JsonName, JsonUUID, Now);
|
||||
} // for idx - root[]
|
||||
Json::Value & Val = root[idx];
|
||||
AString JsonName = Val.get("name", "").asString();
|
||||
AString JsonUUID = StrToLower(MakeUUIDShort(Val.get("id", "").asString()));
|
||||
if (JsonUUID.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
AString lcName = JsonName;
|
||||
m_NameToUUID[StrToLower(lcName)] = sProfile(JsonName, JsonUUID, "", "", Now);
|
||||
} // for idx - root[]
|
||||
} // cCSLock (m_CSNameToUUID)
|
||||
|
||||
// Also cache the UUIDToName:
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
for (size_t idx = 0; idx < JsonCount; ++idx)
|
||||
{
|
||||
Json::Value & Val = root[idx];
|
||||
AString JsonName = Val.get("name", "").asString();
|
||||
AString JsonUUID = StrToLower(MakeUUIDShort(Val.get("id", "").asString()));
|
||||
if (JsonUUID.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
m_UUIDToName[JsonUUID] = sProfile(JsonName, JsonUUID, "", "", Now);
|
||||
} // for idx - root[]
|
||||
}
|
||||
} // while (!NamesToQuery.empty())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
|
||||
{
|
||||
ASSERT(a_UUID.size() == 32);
|
||||
|
||||
// Check if already present:
|
||||
{
|
||||
if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the request address:
|
||||
AString Address = m_UUIDToProfileAddress;
|
||||
ReplaceString(Address, "%UUID%", a_UUID);
|
||||
|
||||
// Create the HTTP request:
|
||||
AString Request;
|
||||
Request += "GET " + Address + " HTTP/1.0\r\n"; // We need to use HTTP 1.0 because we don't handle Chunked transfer encoding
|
||||
Request += "Host: " + m_UUIDToProfileServer + "\r\n";
|
||||
Request += "User-Agent: MCServer\r\n";
|
||||
Request += "Connection: close\r\n";
|
||||
Request += "Content-Length: 0\r\n";
|
||||
Request += "\r\n";
|
||||
|
||||
// Get the response from the server:
|
||||
AString Response;
|
||||
if (!SecureRequest(m_UUIDToProfileServer, Request, Response))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the HTTP status line:
|
||||
const AString Prefix("HTTP/1.1 200 OK");
|
||||
AString HexDump;
|
||||
if (Response.compare(0, Prefix.size(), Prefix))
|
||||
{
|
||||
LOGINFO("%s failed: bad HTTP status line received", __FUNCTION__);
|
||||
LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Erase the HTTP headers from the response:
|
||||
size_t idxHeadersEnd = Response.find("\r\n\r\n");
|
||||
if (idxHeadersEnd == AString::npos)
|
||||
{
|
||||
LOGINFO("%s failed: bad HTTP response header received", __FUNCTION__);
|
||||
LOGD("Response: \n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||
return;
|
||||
}
|
||||
Response.erase(0, idxHeadersEnd + 4);
|
||||
|
||||
// Parse the returned string into Json:
|
||||
Json::Reader reader;
|
||||
Json::Value root;
|
||||
if (!reader.parse(Response, root, false) || !root.isObject())
|
||||
{
|
||||
LOGWARNING("%s failed: Cannot parse received data (NameToUUID) to JSON!", __FUNCTION__);
|
||||
LOGD("Response body:\n%s", CreateHexDump(HexDump, Response.data(), Response.size(), 16).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Example response:
|
||||
{
|
||||
"id": "b1caf24202a841a78055a079c460eee7",
|
||||
"name": "xoft",
|
||||
"properties":
|
||||
[
|
||||
{
|
||||
"name": "textures",
|
||||
"value": "eyJ0aW1lc3RhbXAiOjE0MDcwNzAzMjEyNzEsInByb2ZpbGVJZCI6ImIxY2FmMjQyMDJhODQxYTc4MDU1YTA3OWM0NjBlZWU3IiwicHJvZmlsZU5hbWUiOiJ4b2Z0IiwiaXNQdWJsaWMiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iNzc5YmFiZjVhNTg3Zjk0OGFkNjc0N2VhOTEyNzU0MjliNjg4Mjk1YWUzYzA3YmQwZTJmNWJmNGQwNTIifX19",
|
||||
"signature": "XCty+jGEF39hEPrPhYNnCX087kPaoCjYruzYI/DS4nkL5hbjnkSM5Rh15hnUyv/FHhC8OF5rif3D1tQjtMI19KSVaXoUFXpbJM8/+PB8GDgEbX8Fc3u9nYkzOcM/xfxdYsFAdFhLQMkvase/BZLSuPhdy9DdI+TCrO7xuSTZfYmmwVuWo3w5gCY+mSIAnqltnOzaOOTcly75xvO0WYpVk7nJdnR2tvSi0wfrQPDrIg/uzhX7p0SnDqijmBU4QaNez/TNKiFxy69dAzt0RSotlQzqkDbyVKhhv9a4eY8h3pXi4UMftKEj4FAKczxLImkukJXuOn5NN15/Q+le0rJVBC60/xjKIVzltEsMN6qjWD0lQjey7WEL+4pGhCVuWY5KzuZjFvgqszuJTFz7lo+bcHiceldJtea8/fa02eTRObZvdLxbWC9ZfFY0IhpOVKfcLdno/ddDMNMQMi5kMrJ8MZZ/PcW1w5n7MMGWPGCla1kOaC55AL0QYSMGRVEZqgU9wXI5M7sHGZKGM4mWxkbEJYBkpI/p3GyxWgV6v33ZWlsz65TqlNrR1gCLaoFCm7Sif8NqPBZUAONHYon0roXhin/DyEanS93WV6i6FC1Wisscjq2AcvnOlgTo/5nN/1QsMbjNumuMGo37sqjRqlXoPb8zEUbAhhztYuJjEfQ2Rd8="
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
// Store the returned result into caches:
|
||||
AString PlayerName = root.get("name", "").asString();
|
||||
if (PlayerName.empty())
|
||||
{
|
||||
// No valid playername, bail out
|
||||
return;
|
||||
}
|
||||
Json::Value Properties = root.get("properties", "");
|
||||
Int64 Now = time(NULL);
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToProfile);
|
||||
m_UUIDToProfile[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now);
|
||||
}
|
||||
{
|
||||
cCSLock Lock(m_CSUUIDToName);
|
||||
m_UUIDToName[a_UUID] = sProfile(PlayerName, a_UUID, Properties, Now);
|
||||
}
|
||||
{
|
||||
AString lcPlayerName(PlayerName);
|
||||
cCSLock Lock(m_CSNameToUUID);
|
||||
m_NameToUUID[StrToLower(lcPlayerName)] = sProfile(PlayerName, a_UUID, Properties, Now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user