Advertisement
Guest User

Sending Patches To The Client Through The WoW App

a guest
Nov 16th, 2015
434
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 40.71 KB | None | 0 0
  1. From 8eb6d276a6fd7b391868a186e17d29569efb08fa Mon Sep 17 00:00:00 2001
  2. From: Shoxxo <Shoxxo@exploit.im>
  3. Date: Mon, 16 Nov 2015 18:38:09 +0100
  4. Subject: [PATCH] Sending Patches To The Client Through The WoW App
  5.  
  6. ---
  7. src/common/Logging/Log.cpp                         |    2 +-
  8.  src/server/authserver/Authentication/AuthCodes.cpp |  150 +-
  9.  src/server/authserver/Authentication/AuthCodes.h   |    3 +-
  10.  src/server/authserver/Main.cpp                     |    8 +
  11.  src/server/authserver/Server/AuthSession.cpp       |  397 +-
  12.  src/server/authserver/Server/AuthSession.h         |   56 +-
  13.  src/server/authserver/authserver.conf.dist         |  166 +-
  14.  .../Database/Implementation/LoginDatabase.cpp      |    1 +
  15.  .../Database/Implementation/LoginDatabase.h        |    1 +
  16.  src/server/game/World/World.cpp                    |    2 +-
  17.  rewrite src/server/authserver/Authentication/AuthCodes.cpp (62%)
  18.  
  19. diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp
  20. index 57d399a..51fd0b7 100644
  21. --- a/src/common/Logging/Log.cpp
  22. +++ b/src/common/Logging/Log.cpp
  23. @@ -337,7 +337,7 @@ void Log::LoadFromConfig()
  24.  
  25.      lowestLogLevel = LOG_LEVEL_FATAL;
  26.      AppenderId = 0;
  27. -    m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
  28. +    m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "./log/");
  29.      if (!m_logsDir.empty())
  30.          if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
  31.              m_logsDir.push_back('/');
  32. diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp
  33. dissimilarity index 62%
  34. index 08f091d..999fe63 100644
  35. --- a/src/server/authserver/Authentication/AuthCodes.cpp
  36. +++ b/src/server/authserver/Authentication/AuthCodes.cpp
  37. @@ -1,82 +1,68 @@
  38. -/*
  39. - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
  40. - *
  41. - * This program is free software; you can redistribute it and/or modify it
  42. - * under the terms of the GNU General Public License as published by the
  43. - * Free Software Foundation; either version 2 of the License, or (at your
  44. - * option) any later version.
  45. - *
  46. - * This program is distributed in the hope that it will be useful, but WITHOUT
  47. - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  48. - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  49. - * more details.
  50. - *
  51. - * You should have received a copy of the GNU General Public License along
  52. - * with this program. If not, see <http://www.gnu.org/licenses/>.
  53. - */
  54. -
  55. -#include "AuthCodes.h"
  56. -#include <cstddef>
  57. -
  58. -namespace AuthHelper
  59. -{
  60. -    static RealmBuildInfo const PostBcAcceptedClientBuilds[] =
  61. -    {
  62. -        {15595, 4, 3, 4, ' '},
  63. -        {14545, 4, 2, 2, ' '},
  64. -        {13623, 4, 0, 6, 'a'},
  65. -        {13930, 3, 3, 5, 'a'},                                  // 3.3.5a China Mainland build
  66. -        {12340, 3, 3, 5, 'a'},
  67. -        {11723, 3, 3, 3, 'a'},
  68. -        {11403, 3, 3, 2, ' '},
  69. -        {11159, 3, 3, 0, 'a'},
  70. -        {10505, 3, 2, 2, 'a'},
  71. -        {9947,  3, 1, 3, ' '},
  72. -        {8606,  2, 4, 3, ' '},
  73. -        {0,     0, 0, 0, ' '}                                   // terminator
  74. -    };
  75. -
  76. -    static RealmBuildInfo const PreBcAcceptedClientBuilds[] =
  77. -    {
  78. -        {6141,  1, 12, 3, ' '},
  79. -        {6005,  1, 12, 2, ' '},
  80. -        {5875,  1, 12, 1, ' '},
  81. -        {0,     0, 0, 0, ' '}                                   // terminator
  82. -    };
  83. -
  84. -    bool IsPreBCAcceptedClientBuild(int build)
  85. -    {
  86. -        for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
  87. -            if (PreBcAcceptedClientBuilds[i].Build == build)
  88. -                return true;
  89. -
  90. -        return false;
  91. -    }
  92. -
  93. -    bool IsPostBCAcceptedClientBuild(int build)
  94. -    {
  95. -        for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
  96. -            if (PostBcAcceptedClientBuilds[i].Build == build)
  97. -                return true;
  98. -
  99. -        return false;
  100. -    }
  101. -
  102. -    bool IsAcceptedClientBuild(int build)
  103. -    {
  104. -        return (IsPostBCAcceptedClientBuild(build) || IsPreBCAcceptedClientBuild(build));
  105. -    }
  106. -
  107. -    RealmBuildInfo const* GetBuildInfo(int build)
  108. -    {
  109. -        for (int i = 0; PostBcAcceptedClientBuilds[i].Build; ++i)
  110. -            if (PostBcAcceptedClientBuilds[i].Build == build)
  111. -                return &PostBcAcceptedClientBuilds[i];
  112. -
  113. -        for (int i = 0; PreBcAcceptedClientBuilds[i].Build; ++i)
  114. -            if (PreBcAcceptedClientBuilds[i].Build == build)
  115. -                return &PreBcAcceptedClientBuilds[i];
  116. -
  117. -        return NULL;
  118. -    }
  119. -}
  120. +/*
  121. + * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
  122. + *
  123. + * This program is free software; you can redistribute it and/or modify it
  124. + * under the terms of the GNU General Public License as published by the
  125. + * Free Software Foundation; either version 2 of the License, or (at your
  126. + * option) any later version.
  127. + *
  128. + * This program is distributed in the hope that it will be useful, but WITHOUT
  129. + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  130. + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  131. + * more details.
  132. + *
  133. + * You should have received a copy of the GNU General Public License along
  134. + * with this program. If not, see <http://www.gnu.org/licenses/>.
  135. + */
  136. +
  137. +#include "AuthCodes.h"
  138. +#include "Database/DatabaseEnv.h"
  139. +#include <cstddef>
  140. +#include <map>
  141. +
  142. +typedef std::map<int, RealmBuildInfo*> RealmBuildContainer;
  143. +
  144. +namespace AuthHelper
  145. +{
  146. +    RealmBuildContainer AcceptedClientBuilds;
  147. +    void InitAcceptedClientBuilds()
  148. +    {
  149. +        AcceptedClientBuilds.clear();
  150. +
  151. +        PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_VERSIONS);
  152. +        PreparedQueryResult result = LoginDatabase.Query(stmt);
  153. +
  154. +        if (!result)
  155. +            TC_LOG_ERROR("server.authserver", "Table `versions` is empty. No one will be able to log in.");
  156. +
  157. +        do {
  158. +            Field* fields = result->Fetch();
  159. +            RealmBuildInfo* newBuild = new RealmBuildInfo;
  160. +            newBuild->Build = fields[0].GetUInt32();
  161. +            newBuild->MajorVersion = fields[1].GetUInt32();
  162. +            newBuild->MinorVersion = fields[2].GetUInt32();
  163. +            newBuild->BugfixVersion = fields[3].GetUInt32();
  164. +            newBuild->HotfixVersion = fields[4].GetUInt32();
  165. +            AcceptedClientBuilds[newBuild->Build] = newBuild;
  166. +        } while (result->NextRow());
  167. +    }
  168. +
  169. +    bool IsAcceptedClientBuild(int build)
  170. +    {
  171. +        for (RealmBuildContainer::iterator itr = AcceptedClientBuilds.begin(); itr != AcceptedClientBuilds.end(); itr++)
  172. +            if (itr->second->Build == build)
  173. +                return true;
  174. +
  175. +        return false;
  176. +    }
  177. +
  178. +
  179. +    RealmBuildInfo const* GetBuildInfo(int build)
  180. +    {
  181. +        for (RealmBuildContainer::iterator itr = AcceptedClientBuilds.begin(); itr != AcceptedClientBuilds.end(); itr++)
  182. +            if (itr->second->Build == build)
  183. +                return itr->second;
  184. +
  185. +        return NULL;
  186. +    }
  187. +}
  188. diff --git a/src/server/authserver/Authentication/AuthCodes.h b/src/server/authserver/Authentication/AuthCodes.h
  189. index 7a5df6d..51290f0 100644
  190. --- a/src/server/authserver/Authentication/AuthCodes.h
  191. +++ b/src/server/authserver/Authentication/AuthCodes.h
  192. @@ -88,10 +88,9 @@ struct RealmBuildInfo
  193.  
  194.  namespace AuthHelper
  195.  {
  196. +    void InitAcceptedClientBuilds();
  197.      RealmBuildInfo const* GetBuildInfo(int build);
  198.      bool IsAcceptedClientBuild(int build);
  199. -    bool IsPostBCAcceptedClientBuild(int build);
  200. -    bool IsPreBCAcceptedClientBuild(int build);
  201.  }
  202.  
  203.  #endif
  204. diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
  205. index 205053c..1c6ec5b 100644
  206. --- a/src/server/authserver/Main.cpp
  207. +++ b/src/server/authserver/Main.cpp
  208. @@ -25,6 +25,7 @@
  209.  */
  210.  
  211.  #include "AuthSocketMgr.h"
  212. +#include "AuthCodes.h"
  213.  #include "Common.h"
  214.  #include "Config.h"
  215.  #include "DatabaseEnv.h"
  216. @@ -42,6 +43,7 @@
  217.  
  218.  using boost::asio::ip::tcp;
  219.  using namespace boost::program_options;
  220. +using namespace AuthHelper;
  221.  
  222.  #ifndef _TRINITY_REALM_CONFIG
  223.  # define _TRINITY_REALM_CONFIG  "authserver.conf"
  224. @@ -75,6 +77,8 @@ boost::asio::deadline_timer* _dbPingTimer;
  225.  uint32 _dbPingInterval;
  226.  LoginDatabaseWorkerPool LoginDatabase;
  227.  
  228. +extern Patcher patcher;
  229. +
  230.  int main(int argc, char** argv)
  231.  {
  232.      std::string configFile = _TRINITY_REALM_CONFIG;
  233. @@ -109,6 +113,8 @@ int main(int argc, char** argv)
  234.      TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
  235.      TC_LOG_INFO("server.authserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
  236.  
  237. +    patcher.Initialize();
  238. +  
  239.      // authserver PID file creation
  240.      std::string pidFile = sConfigMgr->GetStringDefault("PidFile", "");
  241.      if (!pidFile.empty())
  242. @@ -126,6 +132,8 @@ int main(int argc, char** argv)
  243.      if (!StartDB())
  244.          return 1;
  245.  
  246. +    AuthHelper::InitAcceptedClientBuilds();
  247. +  
  248.      _ioService = new boost::asio::io_service();
  249.  
  250.      // Get the list of realms for the server
  251. diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
  252. index 28819b8..f96708e 100644
  253. --- a/src/server/authserver/Server/AuthSession.cpp
  254. +++ b/src/server/authserver/Server/AuthSession.cpp
  255. @@ -26,6 +26,7 @@
  256.  #include "Configuration/Config.h"
  257.  #include "RealmList.h"
  258.  #include <boost/lexical_cast.hpp>
  259. +#include <boost/thread.hpp>
  260.  
  261.  using boost::asio::ip::tcp;
  262.  
  263. @@ -107,7 +108,298 @@ typedef struct AUTH_RECONNECT_PROOF_C
  264.      uint8   number_of_keys;
  265.  } sAuthReconnectProof_C;
  266.  
  267. +typedef struct XFER_INIT_C
  268. +{
  269. +    uint8 cmd;
  270. +    uint8 fileNameLen;
  271. +    uint8 fileName[5];
  272. +    uint64 file_size;
  273. +    uint8 md5[MD5_DIGEST_LENGTH];
  274. +} XferInit_C;
  275. +
  276. +typedef struct XFER_RESUME_C
  277. +{
  278. +    uint8 cmd;
  279. +    uint64 pos;
  280. +} XferResume_C;
  281. +
  282. +typedef struct XFER_RESUME_S
  283. +{
  284. +    uint8 cmd;
  285. +    uint64 pos;
  286. +} XferResume_S;
  287. +
  288. +#pragma pack(pop)
  289. +
  290. +Patcher patcher;
  291. +
  292. +PATCH_INFO* Patcher::getPatchInfo(int _build, std::string _locale, bool* fallback)
  293. +{
  294. +    PATCH_INFO* patch = NULL;
  295. +    int locale = *((int*)(_locale.c_str()));
  296. +
  297. +    TC_LOG_INFO("network", "Client with version %i and locale %s (%x) looking for patch.", _build, _locale.c_str(), locale);
  298. +
  299. +    for (Patches::iterator it = _patches.begin(); it != _patches.end(); ++it)
  300. +        if (it->build == _build && it->locale == locale)
  301. +        {
  302. +            patch = &(*it);
  303. +            *fallback = false;
  304. +        }
  305. +
  306. +    return patch;
  307. +}
  308. +
  309. +bool Patcher::PossiblePatching(int _build, std::string _locale)
  310. +{
  311. +    bool temp;
  312. +    return getPatchInfo(_build, _locale, &temp) != NULL;
  313. +}
  314. +
  315. +bool Patcher::InitPatching(int _build, std::string _locale, AuthSession* _session)
  316. +{
  317. +    bool fallback;
  318. +    PATCH_INFO* patch = getPatchInfo(_build, _locale, &fallback);
  319. +
  320. +    // one of them nonzero, start patching.
  321. +    if (patch)
  322. +    {
  323. +        ByteBuffer pkt;
  324. +        pkt << uint8(AUTH_LOGON_PROOF);
  325. +        pkt << uint8(LOGIN_DOWNLOAD_FILE);
  326. +        _session->SendPacket(pkt);
  327. +
  328. +        std::stringstream path;
  329. +        path << m_dataDir << _build << "-" << _locale << ".mpq";
  330. +
  331. +        _session->patch = fopen(path.str().c_str(), "rb");
  332. +        TC_LOG_INFO("network", "Patch: %s", path.str().c_str());
  333. +        XFER_INIT_C xfer;
  334. +        xfer.cmd = XFER_INITIATE;
  335. +        xfer.fileNameLen = 5;
  336. +        xfer.fileName[0] = 'P';
  337. +        xfer.fileName[1] = 'a';
  338. +        xfer.fileName[2] = 'T';
  339. +        xfer.fileName[3] = 'c';
  340. +        xfer.fileName[4] = 'h';
  341. +        xfer.file_size = patch->filesize;
  342. +        memcpy(xfer.md5, patch->md5, MD5_DIGEST_LENGTH);
  343. +        pkt.resize(sizeof(xfer));
  344. +        std::memcpy(pkt.contents(), &xfer, sizeof(xfer));
  345. +        _session->SendPacket(pkt);
  346. +        return true;
  347. +    }
  348. +    else
  349. +    {
  350. +        TC_LOG_INFO("network", "Client with version %i and locale %s did not get a patch.", _build, _locale.c_str());
  351. +        return false;
  352. +    }
  353. +}
  354. +
  355. +// Preload MD5 hashes of existing patch files on server
  356. +#ifndef _WIN32
  357. +#include <dirent.h>
  358. +#include <errno.h>
  359. +
  360. +void Patcher::LoadPatchesInfo()
  361. +{
  362. +    DIR *dirp;
  363. +    struct dirent *dp;
  364. +    dirp = opendir(m_dataDir);
  365. +
  366. +    if (!dirp)
  367. +        return;
  368. +
  369. +    while (dirp)
  370. +    {
  371. +        errno = 0;
  372. +        if ((dp = readdir(dirp)) != NULL)
  373. +        {
  374. +            int l = strlen(dp->d_name);
  375. +
  376. +            if (l < 8)
  377. +                continue;
  378. +
  379. +            if (!memcmp(&dp->d_name[l - 4], ".mpq", 4))
  380. +            {
  381. +                LoadPatchMD5(m_dataDir.c_str(), dp->d_name);
  382. +            }
  383. +        }
  384. +        else
  385. +        {
  386. +            if (errno != 0)
  387. +            {
  388. +                closedir(dirp);
  389. +                return;
  390. +            }
  391. +            break;
  392. +        }
  393. +    }
  394. +
  395. +    if (dirp)
  396. +        closedir(dirp);
  397. +}
  398. +
  399. +#else
  400. +
  401. +void Patcher::LoadPatchesInfo()
  402. +{
  403. +    WIN32_FIND_DATA fil;
  404. +    std::string fileName = m_dataDir + "*.mpq";
  405. +    HANDLE hFil = FindFirstFile(fileName.c_str(), &fil);
  406. +    if (hFil == INVALID_HANDLE_VALUE)
  407. +        return; // no patches were found
  408. +
  409. +    do
  410. +    {
  411. +        LoadPatchMD5(m_dataDir.c_str(), fil.cFileName);
  412. +    } while (FindNextFile(hFil, &fil));
  413. +}
  414. +
  415. +#endif
  416. +
  417. +// Calculate and store MD5 hash for a given patch file
  418. +void Patcher::LoadPatchMD5(const char* szPath, char *szFileName)
  419. +{
  420. +    int build;
  421. +    union
  422. +    {
  423. +        int i;
  424. +        char c[4];
  425. +    } locale;
  426. +
  427. +    if (sscanf(szFileName, "%i-%c%c%c%c.mpq", &build, &locale.c[0], &locale.c[1], &locale.c[2], &locale.c[3]) != 5)
  428. +        return;
  429. +
  430. +    // Try to open the patch file
  431. +    std::string path = szPath;
  432. +    path += szFileName;
  433. +    FILE *patch = fopen(path.c_str(), "rb");
  434. +    if (!patch)
  435. +    {
  436. +        TC_LOG_INFO("network", "Error loading patch %s\n", path.c_str());
  437. +        return;
  438. +    }
  439. +
  440. +    // Calculate the MD5 hash
  441. +    MD5_CTX ctx;
  442. +    MD5_Init(&ctx);
  443. +    uint8* buf = new uint8[512 * 1024];
  444. +
  445. +    while (!feof(patch))
  446. +    {
  447. +        size_t read = fread(buf, 1, 512 * 1024, patch);
  448. +        MD5_Update(&ctx, buf, read);
  449. +    }
  450. +
  451. +    delete[] buf;
  452. +    fseek(patch, 0, SEEK_END);
  453. +    size_t size = ftell(patch);
  454. +    fclose(patch);
  455. +
  456. +    // Store the result in the internal patch hash map
  457. +    PATCH_INFO pi;
  458. +    pi.build = build;
  459. +    pi.locale = locale.i;
  460. +    pi.filesize = uint64(size);
  461. +    MD5_Final((uint8 *)&pi.md5, &ctx);
  462. +    _patches.push_back(pi);
  463. +    TC_LOG_INFO("network", "Added patch for %i %c%c%c%c.", build, locale.c[0], locale.c[1], locale.c[2], locale.c[3]);
  464. +}
  465. +
  466. +PatcherRunnable::PatcherRunnable(AuthSession* session, uint64 _pos, uint64 _size)
  467. +{
  468. +    _session = session;
  469. +    pos = _pos;
  470. +    size = _size;
  471. +    stopped = false;
  472. +}
  473. +
  474. +void PatcherRunnable::stop()
  475. +{
  476. +    stopped = true;
  477. +}
  478. +
  479. +#if defined(__GNUC__)
  480. +#pragma pack(1)
  481. +#else
  482. +#pragma pack(push, 1)
  483. +#endif
  484. +struct TransferDataPacket
  485. +{
  486. +    uint8 cmd;
  487. +    uint16 chunk_size;
  488. +};
  489. +#if defined(__GNUC__)
  490. +#pragma pack()
  491. +#else
  492.  #pragma pack(pop)
  493. +#endif
  494. +
  495. +// Send content of patch file to the client
  496. +void PatcherRunnable::run()
  497. +{
  498. +    TC_LOG_INFO("network", "PatcherRunnable::run(): %ld -> %ld", pos, size);
  499. +
  500. +    while (pos < size && !stopped)
  501. +    {
  502. +        uint64 left = size - pos;
  503. +        uint16 send = (left > 4096) ? 4096 : left;
  504. +
  505. +        char* bytes = new char[sizeof(TransferDataPacket) + send];
  506. +        TransferDataPacket* hdr = (TransferDataPacket*)bytes;
  507. +        hdr->cmd = uint8(XFER_DATA);
  508. +        hdr->chunk_size = send;
  509. +        fread(bytes + sizeof(TransferDataPacket), 1, send, _session->patch);
  510. +
  511. +        ByteBuffer pkt(sizeof(TransferDataPacket) + send);
  512. +        pkt.append(bytes, sizeof(TransferDataPacket) + send);
  513. +
  514. +        _session->SendPacket(pkt);
  515. +        delete[] bytes;
  516. +
  517. +        pos += send;
  518. +
  519. +        _sleep(sConfigMgr->GetIntDefault("PatchPacketDelay", 100));
  520. +    }
  521. +
  522. +    if (!stopped)
  523. +    {
  524. +        fclose(_session->patch);
  525. +        _session->patch = NULL;
  526. +        _session->_patcher = NULL;
  527. +    }
  528. +
  529. +    TC_LOG_INFO("network", "patcher done.");
  530. +}
  531. +
  532. +// Launch the patch hashing mechanism on object creation
  533. +void Patcher::Initialize()
  534. +{
  535. +    m_dataDir = sConfigMgr->GetStringDefault("DataDir", "./data/") + "/patches/";
  536. +    if (!m_dataDir.empty())
  537. +        if ((m_dataDir.at(m_dataDir.length() - 1) != '/') && (m_dataDir.at(m_dataDir.length() - 1) != '\\'))
  538. +            m_dataDir.push_back('/');
  539. +
  540. +    TC_LOG_INFO("network", "Searching for available patches.");
  541. +    LoadPatchesInfo();
  542. +}
  543. +
  544. +// Close patch file descriptor before leaving
  545. +AuthSession::~AuthSession(void)
  546. +{
  547. +    if (patch)
  548. +    {
  549. +        fclose(patch);
  550. +        patch = NULL;
  551. +    }
  552. +    if (_patcher)
  553. +    {
  554. +        _patcher->stop();
  555. +        delete _patcher;
  556. +        _patcher = NULL;
  557. +    }
  558. +}
  559.  
  560.  enum class BufferSizes : uint32
  561.  {
  562. @@ -205,17 +497,49 @@ bool AuthSession::HandleLogonChallenge()
  563.  
  564.      _login.assign((const char*)challenge->I, challenge->I_len);
  565.      _build = challenge->build;
  566. -    _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
  567. +    _expversion = uint8(AuthHelper::IsAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
  568.      _os = (const char*)challenge->os;
  569.  
  570.      if (_os.size() > 4)
  571.          return false;
  572. +  
  573. +    _localizationName.resize(4);
  574. +    for (int i = 0; i < 4; ++i)
  575. +        _localizationName[i] = challenge->country[4 - i - 1];
  576.  
  577.      // Restore string order as its byte order is reversed
  578.      std::reverse(_os.begin(), _os.end());
  579.  
  580.      pkt << uint8(AUTH_LOGON_CHALLENGE);
  581.      pkt << uint8(0x00);
  582. +  
  583. +    if (_expversion == NO_VALID_EXP_FLAG)
  584. +    {
  585. +        if (patcher.PossiblePatching(_build, _localizationName))
  586. +        {
  587. +            uint8 response[119] = {
  588. +                0x00, 0x00, 0x00, 0x72, 0x50, 0xa7, 0xc9, 0x27, 0x4a, 0xfa, 0xb8, 0x77, 0x80, 0x70, 0x22,
  589. +                0xda, 0xb8, 0x3b, 0x06, 0x50, 0x53, 0x4a, 0x16, 0xe2, 0x65, 0xba, 0xe4, 0x43, 0x6f, 0xe3,
  590. +                0x29, 0x36, 0x18, 0xe3, 0x45, 0x01, 0x07, 0x20, 0x89, 0x4b, 0x64, 0x5e, 0x89, 0xe1, 0x53,
  591. +                0x5b, 0xbd, 0xad, 0x5b, 0x8b, 0x29, 0x06, 0x50, 0x53, 0x08, 0x01, 0xb1, 0x8e, 0xbf, 0xbf,
  592. +                0x5e, 0x8f, 0xab, 0x3c, 0x82, 0x87, 0x2a, 0x3e, 0x9b, 0xb7, 0x00, 0x00, 0x00, 0x00, 0x00,
  593. +                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  594. +                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x32, 0xa3,
  595. +                0x49, 0x76, 0x5c, 0x5b, 0x35, 0x9a, 0x93, 0x3c, 0x6f, 0x3c, 0x63, 0x6d, 0xc0, 0x00
  596. +            };
  597. +            ByteBuffer packet;
  598. +            packet.resize(sizeof(response));
  599. +            std::memcpy(packet.contents(), &response, sizeof(response));
  600. +            SendPacket(packet);
  601. +            return true;
  602. +        }
  603. +        else
  604. +        {
  605. +            pkt << uint8(WOW_FAIL_VERSION_INVALID);
  606. +            SendPacket(pkt);
  607. +            return true;
  608. +        }
  609. +    }
  610.  
  611.      // Verify that this IP is not in the ip_banned table
  612.      LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS));
  613. @@ -389,10 +713,6 @@ bool AuthSession::HandleLogonChallenge()
  614.                      uint8 secLevel = fields[5].GetUInt8();
  615.                      _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
  616.  
  617. -                    _localizationName.resize(4);
  618. -                    for (int i = 0; i < 4; ++i)
  619. -                        _localizationName[i] = challenge->country[4 - i - 1];
  620. -
  621.                      TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s is using '%c%c%c%c' locale (%u)",
  622.                          ipAddress.c_str(), port, _login.c_str(),
  623.                          challenge->country[3], challenge->country[2], challenge->country[1], challenge->country[0],
  624. @@ -420,9 +740,15 @@ bool AuthSession::HandleLogonProof()
  625.      // If the client has no valid version
  626.      if (_expversion == NO_VALID_EXP_FLAG)
  627.      {
  628. -        // Check if we have the appropriate patch on the disk
  629. -        TC_LOG_DEBUG("network", "Client with invalid version, patching is not implemented");
  630. -        return false;
  631. +        if (patcher.PossiblePatching(_build, _localizationName))
  632. +        {
  633. +            if (patcher.InitPatching(_build, _localizationName, this))
  634. +                return true;
  635. +            else
  636. +                return false;
  637. +        }
  638. +        else
  639. +            return false;
  640.      }
  641.  
  642.      // Continue the SRP6 calculation based on data received from the client
  643. @@ -670,7 +996,7 @@ bool AuthSession::HandleReconnectChallenge()
  644.  
  645.      // Reinitialize build, expansion and the account securitylevel
  646.      _build = challenge->build;
  647. -    _expversion = uint8(AuthHelper::IsPostBCAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : (AuthHelper::IsPreBCAcceptedClientBuild(_build) ? PRE_BC_EXP_FLAG : NO_VALID_EXP_FLAG));
  648. +    _expversion = uint8(AuthHelper::IsAcceptedClientBuild(_build) ? POST_BC_EXP_FLAG : NO_VALID_EXP_FLAG);
  649.      _os = (const char*)challenge->os;
  650.  
  651.      if (_os.size() > 4)
  652. @@ -798,7 +1124,7 @@ bool AuthSession::HandleRealmList()
  653.      {
  654.          const Realm &realm = i->second;
  655.          // don't work with realms which not compatible with the client
  656. -        bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild));
  657. +        bool okBuild = AuthHelper::IsAcceptedClientBuild(realm.gamebuild);
  658.  
  659.          // No SQL injection. id of realm is controlled by the database.
  660.          uint32 flag = realm.flag;
  661. @@ -888,25 +1214,62 @@ bool AuthSession::HandleRealmList()
  662.  // Resume patch transfer
  663.  bool AuthSession::HandleXferResume()
  664.  {
  665. -    TC_LOG_DEBUG("server.authserver", "Entering _HandleXferResume");
  666. -    //uint8
  667. -    //uint64
  668. -    return true;
  669. +    TC_LOG_DEBUG("server.authserver", "Entering HandleXferResume");
  670. +    XferResume_C* challenge = reinterpret_cast<XferResume_C*>(GetReadBuffer().GetReadPointer());
  671. +
  672. +    // Todo: Send back a packet? I think the client don't get we send data.
  673. +    if (patcher.PossiblePatching(_build, _localizationName))
  674. +    {
  675. +        fseek(patch, 0, SEEK_END);
  676. +        size_t size = ftell(patch);
  677. +
  678. +        fseek(patch, long(challenge->pos), 0);
  679. +
  680. +        if (_patcher)
  681. +        {
  682. +            _patcher->stop();
  683. +            delete _patcher;
  684. +        }
  685. +        _patcher = new PatcherRunnable(this, challenge->pos, size);
  686. +        boost::thread u(&PatcherRunnable::run, _patcher);
  687. +        u.join();
  688. +        return true;
  689. +    }
  690. +    return false;
  691.  }
  692.  
  693.  // Cancel patch transfer
  694.  bool AuthSession::HandleXferCancel()
  695.  {
  696.      TC_LOG_DEBUG("server.authserver", "Entering _HandleXferCancel");
  697. -    //uint8
  698. -    return false;
  699. +    CloseSocket();
  700. +    return true;
  701.  }
  702.  
  703.  // Accept patch transfer
  704.  bool AuthSession::HandleXferAccept()
  705.  {
  706.      TC_LOG_DEBUG("server.authserver", "Entering _HandleXferAccept");
  707. -    //uint8
  708. +
  709. +    // Check packet length and patch existence
  710. +    if (!patch)
  711. +    {
  712. +        TC_LOG_INFO("network", "Error while accepting patch transfer (wrong packet)");
  713. +        return false;
  714. +    }
  715. +
  716. +    // Launch a PatcherRunnable thread, starting at the beginning of the patch file
  717. +    fseek(patch, 0, SEEK_END);
  718. +    size_t size = ftell(patch);
  719. +    fseek(patch, 0, 0);
  720. +
  721. +    if (_patcher)
  722. +    {
  723. +        _patcher->stop();
  724. +        delete _patcher;
  725. +    }
  726. +    _patcher = new PatcherRunnable(this, 0, size);
  727. +    boost::thread u(&PatcherRunnable::run, _patcher);
  728.      return true;
  729.  }
  730.  
  731. diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
  732. index 1151df7..f8b0fa1 100644
  733. --- a/src/server/authserver/Server/AuthSession.h
  734. +++ b/src/server/authserver/Server/AuthSession.h
  735. @@ -25,22 +25,73 @@
  736.  #include "BigNumber.h"
  737.  #include <memory>
  738.  #include <boost/asio/ip/tcp.hpp>
  739. +#include <boost/thread.hpp>
  740. +
  741. +#include <openssl/md5.h>
  742.  
  743.  using boost::asio::ip::tcp;
  744.  
  745.  struct AuthHandler;
  746.  
  747. +class AuthSession;
  748. +
  749. +// clientpatching
  750. +
  751. +typedef struct PATCH_INFO
  752. +{
  753. +    int build;
  754. +    int locale;
  755. +    uint64 filesize;
  756. +    uint8 md5[MD5_DIGEST_LENGTH];
  757. +} PATCH_INFO;
  758. +
  759. +class Patcher
  760. +{
  761. +    typedef std::vector<PATCH_INFO> Patches;
  762. +public:
  763. +    void Initialize();
  764. +
  765. +    void LoadPatchMD5(const char*, char*);
  766. +    bool GetHash(char * pat, uint8 mymd5[16]);
  767. +
  768. +    bool InitPatching(int _build, std::string _locale, AuthSession* _session);
  769. +    bool PossiblePatching(int _build, std::string _locale);
  770. +
  771. +private:
  772. +    PATCH_INFO* getPatchInfo(int _build, std::string _locale, bool* fallback);
  773. +
  774. +    void LoadPatchesInfo();
  775. +    Patches _patches;
  776. +    std::string m_dataDir;
  777. +};
  778. +
  779. +// Launch a thread to transfer a patch to the client
  780. +class PatcherRunnable
  781. +{
  782. +public:
  783. +    PatcherRunnable(AuthSession* session, uint64 pos, uint64 size);
  784. +    void run();
  785. +    void stop();
  786. +
  787. +private:
  788. +    AuthSession* _session;
  789. +    uint64 pos;
  790. +    uint64 size;
  791. +    bool stopped;
  792. +};
  793. +
  794.  class AuthSession : public Socket<AuthSession>
  795.  {
  796.  public:
  797.      static std::unordered_map<uint8, AuthHandler> InitHandlers();
  798.  
  799.      AuthSession(tcp::socket&& socket) : Socket(std::move(socket)),
  800. -        _isAuthenticated(false), _build(0), _expversion(0), _accountSecurityLevel(SEC_PLAYER)
  801. +        _isAuthenticated(false), _build(0), _expversion(0), _accountSecurityLevel(SEC_PLAYER), _patcher(NULL)
  802.      {
  803.          N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
  804.          g.SetDword(7);
  805.      }
  806. +    ~AuthSession();
  807.  
  808.      void Start() override
  809.      {
  810. @@ -49,6 +100,9 @@ public:
  811.  
  812.      void SendPacket(ByteBuffer& packet);
  813.  
  814. +    FILE* patch;
  815. +    PatcherRunnable *_patcher;
  816. +
  817.  protected:
  818.      void ReadHandler() override;
  819.  
  820. diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
  821. index 1b10fa4..4311608 100644
  822. --- a/src/server/authserver/authserver.conf.dist
  823. +++ b/src/server/authserver/authserver.conf.dist
  824. @@ -9,125 +9,85 @@
  825.  #    EXAMPLE CONFIG
  826.  #    AUTH SERVER SETTINGS
  827.  #    MYSQL SETTINGS
  828. -#    UPDATE SETTINGS
  829.  #    LOGGING SYSTEM SETTINGS
  830.  #
  831.  ###################################################################################################
  832. +# AUTH SERVER SETTINGS
  833.  
  834. -###################################################################################################
  835. -# EXAMPLE CONFIG
  836. -#
  837. -#    Variable
  838. -#        Description: Brief description what the variable is doing.
  839. -#        Important:   Annotation for important things about this variable.
  840. -#        Example:     "Example, i.e. if the value is a string"
  841. -#        Default:     10 - (Enabled|Comment|Variable name in case of grouped config options)
  842. -#                     0  - (Disabled|Comment|Variable name in case of grouped config options)
  843. -#
  844. -# Note to developers:
  845. -# - Copy this example to keep the formatting.
  846. -# - Line breaks should be at column 100.
  847. -###################################################################################################
  848. +#    DataDir : Data directory setting.
  849. +DataDir = "./data/"
  850.  
  851. -###################################################################################################
  852. -# AUTH SERVER SETTINGS
  853. -#
  854. -#    LogsDir
  855. -#        Description: Logs directory setting.
  856. -#        Important:   LogsDir needs to be quoted, as the string might contain space characters.
  857. -#                     Logs directory must exists, or log file creation will be disabled.
  858. -#        Default:     "" - (Log files will be stored in the current path)
  859. +#    LogsDir : Logs directory setting.
  860. +LogsDir = "./log/"
  861.  
  862. -LogsDir = ""
  863. +#    PatchPacketDelay: Time between patch packets.
  864. +#        Default: 100
  865. +PatchPacketDelay = 100
  866.  
  867. -#
  868.  #    MaxPingTime
  869.  #        Description: Time (in minutes) between database pings.
  870.  #        Default:     30
  871. -
  872.  MaxPingTime = 30
  873.  
  874. -#
  875.  #    RealmServerPort
  876.  #        Description: TCP port to reach the auth server.
  877.  #        Default:     3724
  878. -
  879.  RealmServerPort = 3724
  880.  
  881. -#
  882. -#
  883.  #    BindIP
  884.  #        Description: Bind auth server to IP/hostname
  885.  #        Default:     "0.0.0.0" - (Bind to all IPs on the system)
  886. -
  887.  BindIP = "0.0.0.0"
  888.  
  889. -#
  890.  #    PidFile
  891.  #        Description: Auth server PID file.
  892.  #        Example:     "./authserver.pid"  - (Enabled)
  893.  #        Default:     ""                  - (Disabled)
  894. -
  895.  PidFile = ""
  896.  
  897. -#
  898.  #    UseProcessors
  899.  #        Description: Processors mask for Windows and Linux based multi-processor systems.
  900.  #        Example:     A computer with 2 CPUs:
  901.  #                     1 - 1st CPU only, 2 - 2nd CPU only, 3 - 1st and 2nd CPU, because 1 | 2 is 3
  902.  #        Default:     0  - (Selected by OS)
  903.  #                     1+ - (Bit mask value of selected processors)
  904. -
  905.  UseProcessors = 0
  906.  
  907. -#
  908.  #    ProcessPriority
  909.  #        Description: Process priority setting for Windows and Linux based systems.
  910.  #        Details:     On Linux, a nice value of -15 is used. (requires superuser). On Windows, process is set to HIGH class.
  911.  #        Default:     0 - (Normal)
  912.  #                     1 - (High)
  913. -
  914.  ProcessPriority = 0
  915.  
  916. -#
  917.  #    RealmsStateUpdateDelay
  918.  #        Description: Time (in seconds) between realm list updates.
  919.  #        Default:     20 - (Enabled)
  920.  #                     0  - (Disabled)
  921. -
  922.  RealmsStateUpdateDelay = 20
  923.  
  924. -#
  925.  #    WrongPass.MaxCount
  926.  #        Description: Number of login attemps with wrong password before the account or IP will be
  927.  #                     banned.
  928.  #        Default:     0  - (Disabled)
  929.  #                     1+ - (Enabled)
  930. -
  931.  WrongPass.MaxCount = 0
  932.  
  933. -#
  934.  #    WrongPass.BanTime
  935.  #        Description: Time (in seconds) for banning account or IP for invalid login attempts.
  936.  #        Default:     600 - (10 minutes)
  937.  #                     0   - (Permanent ban)
  938. -
  939.  WrongPass.BanTime = 600
  940.  
  941. -#
  942.  #    WrongPass.BanType
  943.  #        Description: Ban type for invalid login attempts.
  944.  #        Default:     0 - (Ban IP)
  945.  #                     1 - (Ban Account)
  946. -
  947.  WrongPass.BanType = 0
  948.  
  949.  #
  950.  ###################################################################################################
  951. -
  952. -###################################################################################################
  953.  # MYSQL SETTINGS
  954. -#
  955.  #    LoginDatabaseInfo
  956.  #        Description: Database connection settings for the realm server.
  957.  #        Example:     "hostname;port;username;password;database"
  958. @@ -137,126 +97,33 @@ WrongPass.BanType = 0
  959.  #                     ".;/path/to/unix_socket;username;password;database" - (use Unix sockets on
  960.  #                                                                           Unix/Linux)
  961.  #        Default:     "127.0.0.1;3306;trinity;trinity;auth"
  962. +LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;iwpa"
  963.  
  964. -LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
  965. -
  966. -#
  967.  #    LoginDatabase.WorkerThreads
  968.  #        Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
  969.  #                     statements. Each worker thread is mirrored with its own connection to the
  970.  #        Default:     1
  971. -
  972.  LoginDatabase.WorkerThreads = 1
  973.  
  974. -#
  975.  #    Wrong.Password.Login.Logging
  976.  #        Description: Additionally log attempted wrong password logging
  977.  #        Default:     0 - (Disabled)
  978.  #                     1 - (Enabled)
  979. -
  980.  Wrong.Password.Login.Logging = 0
  981.  
  982.  #
  983.  ###################################################################################################
  984. -
  985. -###################################################################################################
  986. -# UPDATE SETTINGS
  987. -#
  988. -#    Updates.EnableDatabases
  989. -#        Description: A mask that describes which databases shall be updated.
  990. -#
  991. -#        Following flags are available
  992. -#           DATABASE_LOGIN     = 1, // Auth database
  993. -#
  994. -#        Default:     0  - (All Disabled)
  995. -#                     1  - (All Enabled)
  996. -
  997. -Updates.EnableDatabases = 0
  998. -
  999. -#
  1000. -#    Updates.SourcePath
  1001. -#        Description: The path to your TrinityCore source directory.
  1002. -#                     If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
  1003. -#        Example:     "../TrinityCore"
  1004. -#        Default:     ""
  1005. -
  1006. -Updates.SourcePath  = ""
  1007. -
  1008. -#
  1009. -#    Updates.MySqlCLIPath
  1010. -#        Description: The path to your mysql cli binary.
  1011. -#                     If the path is left empty, built-in path from cmake is used.
  1012. -#        Example:     "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
  1013. -#                     "mysql.exe"
  1014. -#                     "/usr/bin/mysql"
  1015. -#        Default:     ""
  1016. -
  1017. -Updates.MySqlCLIPath = ""
  1018. -
  1019. -#
  1020. -#    Updates.AutoSetup
  1021. -#        Description: Auto populate empty databases.
  1022. -#        Default:     1 - (Enabled)
  1023. -#                     0 - (Disabled)
  1024. -
  1025. -Updates.AutoSetup   = 1
  1026. -
  1027. -#
  1028. -#    Updates.Redundancy
  1029. -#        Description: Perform data redundancy checks through hashing
  1030. -#                     to detect changes on sql updates and reapply it.
  1031. -#        Default:     1 - (Enabled)
  1032. -#                     0 - (Disabled)
  1033. -
  1034. -Updates.Redundancy  = 1
  1035. -
  1036. -#
  1037. -#    Updates.ArchivedRedundancy
  1038. -#        Description: Check hashes of archived updates (slows down startup).
  1039. -#        Default:     0 - (Disabled)
  1040. -#                     1 - (Enabled)
  1041. -
  1042. -Updates.ArchivedRedundancy = 0
  1043. -
  1044. -#
  1045. -#    Updates.AllowRehash
  1046. -#        Description: Inserts the current file hash in the database if it is left empty.
  1047. -#                     Useful if you want to mark a file as applied but you don't know its hash.
  1048. -#        Default:     1 - (Enabled)
  1049. -#                     0 - (Disabled)
  1050. -
  1051. -Updates.AllowRehash = 1
  1052. -
  1053. -#
  1054. -#    Updates.CleanDeadRefMaxCount
  1055. -#        Description: Cleans dead/ orphaned references that occur if an update was removed or renamed and edited in one step.
  1056. -#                     It only starts the clean up if the count of the missing updates is below or equal the Updates.CleanDeadRefMaxCount value.
  1057. -#                     This way prevents erasing of the update history due to wrong source directory state (maybe wrong branch or bad revision).
  1058. -#                     Disable this if you want to know if the database is in a possible "dirty state".
  1059. -#        Default:     3 - (Enabled)
  1060. -#                     0 - (Disabled)
  1061. -#                    -1 - (Enabled - unlimited)
  1062. -
  1063. -Updates.CleanDeadRefMaxCount = 3
  1064. -
  1065. -#
  1066. -###################################################################################################
  1067. -
  1068. -###################################################################################################
  1069. -#
  1070.  #  LOGGING SYSTEM SETTINGS
  1071. -#
  1072. +
  1073.  #  Appender config values: Given a appender "name"
  1074.  #    Appender.name
  1075.  #        Description: Defines 'where to log'
  1076.  #        Format:      Type,LogLevel,Flags,optional1,optional2,optional3
  1077. -#
  1078.  #                     Type
  1079.  #                         0 - (None)
  1080.  #                         1 - (Console)
  1081.  #                         2 - (File)
  1082.  #                         3 - (DB)
  1083. -#
  1084.  #                     LogLevel
  1085.  #                         0 - (Disabled)
  1086.  #                         1 - (Trace)
  1087. @@ -265,7 +132,6 @@ Updates.CleanDeadRefMaxCount = 3
  1088.  #                         4 - (Warn)
  1089.  #                         5 - (Error)
  1090.  #                         6 - (Fatal)
  1091. -#
  1092.  #                     Flags:
  1093.  #                         0 - None
  1094.  #                         1 - Prefix Timestamp to the text
  1095. @@ -273,7 +139,6 @@ Updates.CleanDeadRefMaxCount = 3
  1096.  #                         4 - Prefix Log Filter type to the text
  1097.  #                         8 - Append timestamp to the log file name. Format: YYYY-MM-DD_HH-MM-SS (Only used with Type = 2)
  1098.  #                        16 - Make a backup of existing file before overwrite (Only used with Mode = w)
  1099. -#
  1100.  #                     Colors (read as optional1 if Type = Console)
  1101.  #                         Format: "fatal error warn info debug trace"
  1102.  #                         0 - BLACK
  1103. @@ -292,22 +157,17 @@ Updates.CleanDeadRefMaxCount = 3
  1104.  #                        13 - LCYAN
  1105.  #                        14 - WHITE
  1106.  #                         Example: "13 11 9 5 3 1"
  1107. -#
  1108.  #                     File: Name of the file (read as optional1 if Type = File)
  1109.  #                         Allows to use one "%s" to create dynamic files
  1110. -#
  1111.  #                     Mode: Mode to open the file (read as optional2 if Type = File)
  1112.  #                          a - (Append)
  1113.  #                          w - (Overwrite)
  1114. -#
  1115.  #                     MaxFileSize: Maximum file size of the log file before creating a new log file
  1116.  #                     (read as optional3 if Type = File)
  1117.  #                         Size is measured in bytes expressed in a 64-bit unsigned integer.
  1118.  #                         Maximum value is 4294967295 (4 gb). Leave blank for no limit.
  1119.  #                         NOTE: Does not work with dynamic filenames.
  1120.  #                         Example:  536870912 (512 mb)
  1121. -#
  1122. -
  1123.  Appender.Console=1,2,0
  1124.  Appender.Auth=2,2,0,Auth.log,w
  1125.  
  1126. @@ -315,7 +175,6 @@ Appender.Auth=2,2,0,Auth.log,w
  1127.  #    Logger.name
  1128.  #        Description: Defines 'What to log'
  1129.  #        Format:      LogLevel,AppenderList
  1130. -#
  1131.  #                     LogLevel
  1132.  #                         0 - (Disabled)
  1133.  #                         1 - (Trace)
  1134. @@ -324,12 +183,9 @@ Appender.Auth=2,2,0,Auth.log,w
  1135.  #                         4 - (Warn)
  1136.  #                         5 - (Error)
  1137.  #                         6 - (Fatal)
  1138. -#
  1139.  #                     AppenderList: List of appenders linked to logger
  1140.  #                     (Using spaces as separator).
  1141. -#
  1142. -
  1143.  Logger.root=3,Console Auth
  1144.  
  1145.  #
  1146. -###################################################################################################
  1147. +###################################################################################################
  1148. \ No newline at end of file
  1149. diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
  1150. index de003c2..95bd3a4 100644
  1151. --- a/src/server/database/Database/Implementation/LoginDatabase.cpp
  1152. +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
  1153. @@ -110,6 +110,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
  1154.      // 0: string, 1: string, 2: string                      // Complete name: "Login_Insert_Failed_Account_Login_due_password_IP_Logging"
  1155.      PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
  1156.      PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH);
  1157. +    PrepareStatement(LOGIN_SEL_VERSIONS, "SELECT Build, MajorVersion, MinorVersion, BugfixVersion, HotfixVersion FROM versions", CONNECTION_SYNCH);
  1158.  
  1159.      PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_BOTH);
  1160.      PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION, "INSERT INTO rbac_account_permissions (accountId, permissionId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC);
  1161. diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
  1162. index 3b30105..1a60fc7 100644
  1163. --- a/src/server/database/Database/Implementation/LoginDatabase.h
  1164. +++ b/src/server/database/Database/Implementation/LoginDatabase.h
  1165. @@ -108,6 +108,7 @@ enum LoginDatabaseStatements
  1166.      LOGIN_INS_FACL_IP_LOGGING,
  1167.      LOGIN_INS_CHAR_IP_LOGGING,
  1168.      LOGIN_INS_FALP_IP_LOGGING,
  1169. +    LOGIN_SEL_VERSIONS,
  1170.  
  1171.      LOGIN_SEL_ACCOUNT_ACCESS_BY_ID,
  1172.      LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS,
  1173. diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
  1174. index c41caa8..c10f8b1 100644
  1175. --- a/src/server/game/World/World.cpp
  1176. +++ b/src/server/game/World/World.cpp
  1177. @@ -1139,7 +1139,7 @@ void World::LoadConfigSettings(bool reload)
  1178.      }
  1179.  
  1180.      ///- Read the "Data" directory from the config file
  1181. -    std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./");
  1182. +    std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./data/");
  1183.      if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\'))
  1184.          dataPath.push_back('/');
  1185.  
  1186. --
  1187. 1.9.5.msysgit.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement