TrinityCore
Loading...
Searching...
No Matches
ClientBuildInfo.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ClientBuildInfo.h"
19#include "DatabaseEnv.h"
20#include "Log.h"
21#include "Util.h"
22#include <algorithm>
23#include <cctype>
24
25namespace
26{
27std::vector<ClientBuild::Info> Builds;
28}
29
30namespace ClientBuild
31{
32std::array<char, 5> ToCharArray(uint32 value)
33{
34 auto normalize = [](uint8 c) -> char
35 {
36 if (!c || std::isprint(c))
37 return char(c);
38 return ' ';
39 };
40
41 std::array<char, 5> chars = { char((value >> 24) & 0xFF), char((value >> 16) & 0xFF), char((value >> 8) & 0xFF), char(value & 0xFF), '\0' };
42
43 auto firstNonZero = std::ranges::find_if(chars, [](char c) { return c != '\0'; });
44 if (firstNonZero != chars.end())
45 {
46 // move leading zeros to end
47 std::rotate(chars.begin(), firstNonZero, chars.end());
48
49 // ensure we only have printable characters remaining
50 std::ranges::transform(chars, chars.begin(), normalize);
51 }
52
53 return chars;
54}
55
56bool Platform::IsValid(std::string_view platform)
57{
58 if (platform.length() > sizeof(uint32))
59 return false;
60
61 switch (ToFourCC(platform))
62 {
63 case Win_x86:
64 case Win_x64:
65 case Win_arm64:
66 case Mac_x86:
67 case Mac_x64:
68 case Mac_arm64:
69 return true;
70 default:
71 break;
72 }
73
74 return false;
75}
76
77bool PlatformType::IsValid(std::string_view platformType)
78{
79 if (platformType.length() > sizeof(uint32))
80 return false;
81
82 switch (ToFourCC(platformType))
83 {
84 case Windows:
85 case macOS:
86 return true;
87 default:
88 break;
89 }
90
91 return false;
92}
93
94bool Arch::IsValid(std::string_view arch)
95{
96 if (arch.length() > sizeof(uint32))
97 return false;
98
99 switch (ToFourCC(arch))
100 {
101 case x86:
102 case x64:
103 case Arm32:
104 case Arm64:
105 case WA32:
106 return true;
107 default:
108 break;
109 }
110
111 return false;
112}
113
114bool Type::IsValid(std::string_view type)
115{
116 if (type.length() > sizeof(uint32))
117 return false;
118
119 switch (ToFourCC(type))
120 {
121 case Retail:
122 case RetailChina:
123 case Beta:
124 case BetaRelease:
125 case Ptr:
126 case PtrRelease:
127 return true;
128 default:
129 break;
130 }
131
132 return false;
133}
134
136{
137 Builds.clear();
138
139 // 0 1 2 3 4
140 if (QueryResult result = LoginDatabase.Query("SELECT majorVersion, minorVersion, bugfixVersion, hotfixVersion, build FROM build_info ORDER BY build ASC"))
141 {
142 do
143 {
144 Field* fields = result->Fetch();
145 Info& build = Builds.emplace_back();
146 build.MajorVersion = fields[0].GetUInt32();
147 build.MinorVersion = fields[1].GetUInt32();
148 build.BugfixVersion = fields[2].GetUInt32();
149 std::string_view hotfixVersion = fields[3].GetStringView();
150 if (hotfixVersion.length() < build.HotfixVersion.size())
151 std::ranges::copy(hotfixVersion, build.HotfixVersion.begin());
152 else
153 build.HotfixVersion = { };
154
155 build.Build = fields[4].GetUInt32();
156
157 } while (result->NextRow());
158 }
159
160 // 0 1 2 3 4
161 if (QueryResult result = LoginDatabase.Query("SELECT `build`, `platform`, `arch`, `type`, `key` FROM `build_auth_key`"))
162 {
163 do
164 {
165 Field* fields = result->Fetch();
166
167 uint32 build = fields[0].GetInt32();
168 auto buildInfo = std::ranges::find(Builds, build, &Info::Build);
169 if (buildInfo == Builds.end())
170 {
171 TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Unknown `build` {} in `build_auth_key` - missing from `build_info`, skipped.", build);
172 continue;
173 }
174
175 std::string_view platformType = fields[1].GetStringView();
176 if (!PlatformType::IsValid(platformType))
177 {
178 TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Invalid platform {} for `build` {} in `build_auth_key`, skipped.", platformType, build);
179 continue;
180 }
181
182 std::string_view arch = fields[2].GetStringView();
183 if (!Arch::IsValid(arch))
184 {
185 TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Invalid `arch` {} for `build` {} in `build_auth_key`, skipped.", arch, build);
186 continue;
187 }
188
189 std::string_view type = fields[3].GetStringView();
190 if (!Type::IsValid(type))
191 {
192 TC_LOG_ERROR("sql.sql", "ClientBuild::LoadBuildInfo: Invalid `type` {} for `build` {} in `build_auth_key`, skipped.", type, build);
193 continue;
194 }
195
196 AuthKey& buildKey = buildInfo->AuthKeys.emplace_back();
197 buildKey.Variant = { .Platform = ToFourCC(platformType), .Arch = ToFourCC(arch), .Type = ToFourCC(type) };
198 buildKey.Key = fields[4].GetBinary<AuthKey::Size>();
199
200 } while (result->NextRow());
201 }
202}
203
205{
206 auto buildInfo = std::ranges::find(Builds, build, &Info::Build);
207 return buildInfo != Builds.end() ? &*buildInfo : nullptr;
208}
209
211{
212 auto buildInfo = std::ranges::lower_bound(Builds, build, {}, &Info::Build);
213 return buildInfo != Builds.end() ? (buildInfo->MajorVersion * 10000 + buildInfo->MinorVersion * 100 + buildInfo->BugfixVersion) : 0;
214}
215}
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< LoginDatabaseConnection > LoginDatabase
Accessor to the realm/login database.
uint8_t uint8
Definition Define.h:156
uint32_t uint32
Definition Define.h:154
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
Class used to access individual fields of database query result.
Definition Field.h:94
std::vector< uint8 > GetBinary() const noexcept
Definition Field.cpp:125
uint32 GetUInt32() const noexcept
Definition Field.cpp:57
std::string_view GetStringView() const noexcept
Definition Field.cpp:118
int32 GetInt32() const noexcept
Definition Field.cpp:64
constexpr uint32 x64
constexpr uint32 WA32
constexpr uint32 Arm64
constexpr uint32 x86
TC_SHARED_API bool IsValid(std::string_view arch)
constexpr uint32 Arm32
TC_SHARED_API bool IsValid(std::string_view platformType)
constexpr uint32 Win_x86
constexpr uint32 Win_x64
constexpr uint32 Win_arm64
TC_SHARED_API bool IsValid(std::string_view platform)
constexpr uint32 Mac_arm64
constexpr uint32 Mac_x64
constexpr uint32 Mac_x86
constexpr uint32 Retail
constexpr uint32 Ptr
constexpr uint32 BetaRelease
constexpr uint32 Beta
constexpr uint32 RetailChina
TC_SHARED_API bool IsValid(std::string_view type)
constexpr uint32 PtrRelease
uint32 GetMinorMajorBugfixVersionForBuild(uint32 build)
constexpr uint32 ToFourCC(std::string_view text)
Info const * GetBuildInfo(uint32 build)
std::array< char, 5 > ToCharArray(uint32 value)
std::array< uint8, Size > Key
static constexpr std::size_t Size
std::array< char, 4 > HotfixVersion