Advertisement
Guest User

Untitled

a guest
Apr 18th, 2020
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.31 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include <sstream>
  3. #ifndef __WIN32__
  4. #include <ifaddrs.h>
  5. #endif
  6.  
  7. #include "constants.h"
  8. #include "utils.h"
  9. #include "log.h"
  10. #include "desc.h"
  11. #include "desc_manager.h"
  12. #include "item_manager.h"
  13. #include "p2p.h"
  14. #include "char.h"
  15. #include "ip_ban.h"
  16. #include "war_map.h"
  17. #include "locale_service.h"
  18. #include "config.h"
  19. #include "dev_log.h"
  20. #include "db.h"
  21. #include "skill_power.h"
  22. #include "check_server.h"
  23.  
  24. using std::string;
  25.  
  26. BYTE g_bChannel = 0;
  27. WORD mother_port = 50080;
  28. int passes_per_sec = 25;
  29. WORD db_port = 0;
  30. WORD p2p_port = 50900;
  31. char db_addr[ADDRESS_MAX_LEN + 1];
  32. int save_event_second_cycle = passes_per_sec * 120; // 3ºÐ
  33. int ping_event_second_cycle = passes_per_sec * 60;
  34. bool g_bNoMoreClient = false;
  35. bool g_bNoRegen = false;
  36. bool g_bNoPasspod = false;
  37.  
  38. // TRAFFIC_PROFILER
  39. bool g_bTrafficProfileOn = false;
  40. DWORD g_dwTrafficProfileFlushCycle = 3600;
  41. // END_OF_TRAFFIC_PROFILER
  42.  
  43. int test_server = 0;
  44. int speed_server = 0;
  45. #ifdef __AUCTION__
  46. int auction_server = 0;
  47. #endif
  48. bool distribution_test_server = false;
  49. bool china_event_server = false;
  50. bool guild_mark_server = true;
  51. BYTE guild_mark_min_level = 1;
  52. bool no_wander = false;
  53. int g_iUserLimit = 32768;
  54.  
  55. char g_szPublicIP[16] = "0";
  56. char g_szInternalIP[16] = "0";
  57. bool g_bSkillDisable = false;
  58. int g_iFullUserCount = 1000;
  59. int g_iBusyUserCount = 500;
  60. //Canada
  61. //int g_iFullUserCount = 600;
  62. //int g_iBusyUserCount = 350;
  63. //Brazil
  64. //int g_iFullUserCount = 650;
  65. //int g_iBusyUserCount = 450;
  66. bool g_bEmpireWhisper = true;
  67. BYTE g_bAuthServer = false;
  68.  
  69. bool g_bCheckClientVersion = true;
  70. string g_stClientVersion = "4353457799";
  71.  
  72. BYTE g_bBilling = false;
  73.  
  74. string g_stAuthMasterIP;
  75. WORD g_wAuthMasterPort = 0;
  76.  
  77.  
  78. static std::set<DWORD> s_set_dwFileCRC;
  79. static std::set<DWORD> s_set_dwProcessCRC;
  80.  
  81. string g_stHostname = "";
  82. string g_table_postfix = "";
  83.  
  84. string g_stQuestDir = "./quest";
  85. //string g_stQuestObjectDir = "./quest/object";
  86. string g_stDefaultQuestObjectDir = "./quest/object";
  87. std::set<string> g_setQuestObjectDir;
  88.  
  89. std::vector<std::string> g_stAdminPageIP;
  90. std::string g_stAdminPagePassword = "onex.ws";
  91.  
  92. string g_stBlockDate = "30000705";
  93.  
  94. extern string g_stLocale;
  95.  
  96. char teen_addr[ADDRESS_MAX_LEN + 1] = {0};
  97. WORD teen_port = 0;
  98.  
  99. BYTE gTimeToStartPvP = 3; //contador pvp by dragonslayer
  100.  
  101. int SPEEDHACK_LIMIT_COUNT = 50;
  102. int SPEEDHACK_LIMIT_BONUS = 80;
  103. int g_iSyncHackLimitCount = 20; // 10 -> 20 2013 09 11 CYH
  104.  
  105. //½Ã¾ß = VIEW_RANGE + VIEW_BONUS_RANGE
  106. //VIEW_BONUSE_RANGE : Ŭ¶óÀ̾ðÆ®¿Í ½Ã¾ß 󸮿¡¼­³Ê¹« µü ¶³¾îÁú°æ¿ì ¹®Á¦°¡ ¹ß»ýÇÒ¼öÀÖ¾î 500CMÀÇ ¿©ºÐÀ» Ç×»óÁØ´Ù.
  107. int VIEW_RANGE = 5000;
  108. int VIEW_BONUS_RANGE = 500;
  109.  
  110. int g_server_id = 0;
  111. string g_strWebMallURL = "www.metin2nb.ro";
  112.  
  113. unsigned int g_uiSpamBlockDuration = 60 * 15; // ±âº» 15ºÐ
  114. unsigned int g_uiSpamBlockScore = 100; // ±âº» 100Á¡
  115. unsigned int g_uiSpamReloadCycle = 60 * 10; // ±âº» 10ºÐ
  116.  
  117. bool g_bCheckMultiHack = true;
  118.  
  119. int g_iSpamBlockMaxLevel = 10;
  120.  
  121. void LoadStateUserCount();
  122. void LoadValidCRCList();
  123. bool LoadClientVersion();
  124. bool g_protectNormalPlayer = false; // ¹ü¹ýÀÚ°¡ "ÆòÈ­¸ðµå" ÀÎ ÀϹÝÀ¯Àú¸¦ °ø°ÝÇÏÁö ¸øÇÔ
  125. bool g_noticeBattleZone = false; // Á߸³Áö´ë¿¡ ÀÔÀåÇÏ¸é ¾È³»¸Þ¼¼Áö¸¦ ¾Ë·ÁÁÜ
  126.  
  127. bool isHackShieldEnable = false;
  128. int HackShield_FirstCheckWaitTime = passes_per_sec * 30;
  129. int HackShield_CheckCycleTime = passes_per_sec * 180;
  130.  
  131. bool bXTrapEnabled = false;
  132.  
  133. int gPlayerMaxLevel = 151;
  134.  
  135. bool g_BlockCharCreation = false;
  136.  
  137.  
  138. //OPENID
  139. int openid_server = 0;
  140. char openid_host[256];
  141. char openid_uri[256];
  142.  
  143. bool is_string_true(const char * string)
  144. {
  145. bool result = 0;
  146. if (isnhdigit(*string))
  147. {
  148. str_to_number(result, string);
  149. return result > 0 ? true : false;
  150. }
  151. else if (LOWER(*string) == 't')
  152. return true;
  153. else
  154. return false;
  155. }
  156.  
  157. static std::set<int> s_set_map_allows;
  158.  
  159. bool map_allow_find(int index)
  160. {
  161. if (g_bAuthServer)
  162. return false;
  163.  
  164. if (s_set_map_allows.find(index) == s_set_map_allows.end())
  165. return false;
  166.  
  167. return true;
  168. }
  169.  
  170. void map_allow_log()
  171. {
  172. std::set<int>::iterator i;
  173.  
  174. for (i = s_set_map_allows.begin(); i != s_set_map_allows.end(); ++i)
  175. sys_log(0, "MAP_ALLOW: %d", *i);
  176. }
  177.  
  178. void map_allow_add(int index)
  179. {
  180. // if (map_allow_find(index) == true)
  181. // {
  182. // fprintf(stdout, "!!! FATAL ERROR !!! multiple MAP_ALLOW setting!!\n");
  183. // exit(1);
  184. // }
  185.  
  186. fprintf(stdout, "MAP ALLOW %d\n", index);
  187. s_set_map_allows.insert(index);
  188. }
  189.  
  190. void map_allow_copy(long * pl, int size)
  191. {
  192. int iCount = 0;
  193. std::set<int>::iterator it = s_set_map_allows.begin();
  194.  
  195. while (it != s_set_map_allows.end())
  196. {
  197. int i = *(it++);
  198. *(pl++) = i;
  199.  
  200. if (++iCount > size)
  201. break;
  202. }
  203. }
  204.  
  205. static std::set<int> s_set_map;
  206.  
  207. bool isExistMap(int iIndex)
  208. {
  209. if(g_bAuthServer)
  210. return false;
  211.  
  212. if(s_set_map.find(iIndex) == s_set_map.end())
  213. return false;
  214.  
  215. return true;
  216. }
  217. void addMap(int iIndex)
  218. {
  219. if(isExistMap(iIndex))
  220. {
  221. fprintf(stdout,"We can't continue!");
  222. exit(1);
  223. }
  224.  
  225. s_set_map.insert(iIndex);
  226. fprintf(stdout, "ADDED_MAP_FOR_DISABLE_RANK %d",iIndex);
  227. }
  228.  
  229. static void FN_add_adminpageIP(char *line)
  230. {
  231. char *last;
  232. const char *delim = " \t\r\n";
  233. char *v = strtok_r(line, delim, &last);
  234.  
  235. while (v)
  236. {
  237. g_stAdminPageIP.push_back(v);
  238. v = strtok_r(NULL, delim, &last);
  239. }
  240. }
  241.  
  242. static void FN_log_adminpage()
  243. {
  244. itertype(g_stAdminPageIP) iter = g_stAdminPageIP.begin();
  245.  
  246. while (iter != g_stAdminPageIP.end())
  247. {
  248. dev_log(LOG_DEB0, "ADMIN_PAGE_IP = %s", (*iter).c_str());
  249. ++iter;
  250. }
  251.  
  252. dev_log(LOG_DEB0, "ADMIN_PAGE_PASSWORD = %s", g_stAdminPagePassword.c_str());
  253. }
  254.  
  255.  
  256. bool GetIPInfo()
  257. {
  258. #ifndef __WIN32__
  259. struct ifaddrs* ifaddrp = NULL;
  260.  
  261. if (0 != getifaddrs(&ifaddrp))
  262. return false;
  263.  
  264. for (struct ifaddrs* ifap = ifaddrp; NULL != ifap; ifap = ifap->ifa_next)
  265. {
  266. struct sockaddr_in * sai = (struct sockaddr_in *) ifap->ifa_addr;
  267.  
  268. if (!ifap->ifa_netmask || // ignore if no netmask
  269. sai->sin_addr.s_addr == 0 || // ignore if address is 0.0.0.0
  270. sai->sin_addr.s_addr == 16777343) // ignore if address is 127.0.0.1
  271. continue;
  272. #else
  273. WSADATA wsa_data;
  274. char host_name[100];
  275. HOSTENT* host_ent;
  276. int n = 0;
  277.  
  278. if (WSAStartup(0x0101, &wsa_data)) {
  279. return false;
  280. }
  281.  
  282. gethostname(host_name, sizeof(host_name));
  283. host_ent = gethostbyname(host_name);
  284. if (host_ent == NULL) {
  285. return false;
  286. }
  287. for (; host_ent->h_addr_list[n] != NULL; ++n) {
  288. struct sockaddr_in addr;
  289. struct sockaddr_in* sai = &addr;
  290. memcpy(&sai->sin_addr.s_addr, host_ent->h_addr_list[n], host_ent->h_length);
  291. #endif
  292.  
  293. char * netip = inet_ntoa(sai->sin_addr);
  294.  
  295. if (g_szPublicIP[0] == '0')
  296. {
  297. strlcpy(g_szPublicIP, netip, sizeof(g_szPublicIP));
  298. #ifndef __WIN32__
  299. fprintf(stderr, "PUBLIC_IP: %s interface %s\n", netip, ifap->ifa_name);
  300. #else
  301. fprintf(stderr, "PUBLIC_IP: %s\n", netip);
  302. #endif
  303. }
  304. }
  305.  
  306. #ifndef __WIN32__
  307. freeifaddrs(ifaddrp);
  308. #else
  309. WSACleanup();
  310. #endif
  311.  
  312. if (g_szPublicIP[0] != '0')
  313. return true;
  314. else
  315. return false;
  316. }
  317.  
  318.  
  319. void config_init(const string& st_localeServiceName)
  320. {
  321. FILE *fp;
  322.  
  323. char buf[256];
  324. char token_string[256];
  325. char value_string[256];
  326.  
  327. // LOCALE_SERVICE
  328. string st_configFileName;
  329.  
  330. st_configFileName.reserve(32);
  331. st_configFileName = "CONFIG";
  332.  
  333. if (!st_localeServiceName.empty())
  334. {
  335. st_configFileName += ".";
  336. st_configFileName += st_localeServiceName;
  337. }
  338. // END_OF_LOCALE_SERVICE
  339.  
  340. if (!(fp = fopen(st_configFileName.c_str(), "r")))
  341. {
  342. fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
  343. exit(1);
  344. }
  345.  
  346. if (!GetIPInfo())
  347. {
  348. fprintf(stderr, "Can not get public ip address\n");
  349. exit(1);
  350. }
  351.  
  352. char db_host[2][64], db_user[2][64], db_pwd[2][64], db_db[2][64];
  353. // ... ¾Æ... db_port´Â ÀÌ¹Ì Àִµ¥... ³×ÀÌ¹Ö ¾îÂîÇؾßÇÔ...
  354. int mysql_db_port[2];
  355.  
  356. for (int n = 0; n < 2; ++n)
  357. {
  358. *db_host[n] = '\0';
  359. *db_user[n] = '\0';
  360. *db_pwd[n]= '\0';
  361. *db_db[n]= '\0';
  362. mysql_db_port[n] = 0;
  363. }
  364.  
  365. char log_host[64], log_user[64], log_pwd[64], log_db[64];
  366. int log_port = 0;
  367.  
  368. *log_host = '\0';
  369. *log_user = '\0';
  370. *log_pwd = '\0';
  371. *log_db = '\0';
  372.  
  373.  
  374. // DB¿¡¼­ ·ÎÄÉÀÏÁ¤º¸¸¦ ¼¼ÆÃÇϱâÀ§Çؼ­´Â ´Ù¸¥ ¼¼Æ𪺸´Ù ¼±ÇàµÇ¾î¼­
  375. // DBÁ¤º¸¸¸ Àоî¿Í ·ÎÄÉÀÏ ¼¼ÆÃÀ» ÇÑÈÄ ´Ù¸¥ ¼¼ÆÃÀ» Àû¿ë½ÃÄѾßÇÑ´Ù.
  376. // ÀÌÀ¯´Â ·ÎÄÉÀÏ°ü·ÃµÈ ÃʱâÈ­ ·çƾÀÌ °÷°÷¿¡ Á¸ÀçÇϱ⠶§¹®.
  377.  
  378. bool isCommonSQL = false;
  379. bool isPlayerSQL = false;
  380.  
  381. FILE* fpOnlyForDB;
  382.  
  383. if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
  384. {
  385. fprintf(stderr, "Can not open [%s]\n", st_configFileName.c_str());
  386. exit(1);
  387. }
  388.  
  389. while (fgets(buf, 256, fpOnlyForDB))
  390. {
  391. parse_token(buf, token_string, value_string);
  392.  
  393. TOKEN("BLOCK_LOGIN")
  394. {
  395. g_stBlockDate = value_string;
  396. }
  397.  
  398. TOKEN("adminpage_ip")
  399. {
  400. FN_add_adminpageIP(value_string);
  401. //g_stAdminPageIP[0] = value_string;
  402. }
  403.  
  404. TOKEN("adminpage_ip1")
  405. {
  406. FN_add_adminpageIP(value_string);
  407. //g_stAdminPageIP[0] = value_string;
  408. }
  409.  
  410. TOKEN("adminpage_ip2")
  411. {
  412. FN_add_adminpageIP(value_string);
  413. //g_stAdminPageIP[1] = value_string;
  414. }
  415.  
  416. TOKEN("adminpage_ip3")
  417. {
  418. FN_add_adminpageIP(value_string);
  419. //g_stAdminPageIP[2] = value_string;
  420. }
  421.  
  422. TOKEN("adminpage_password")
  423. {
  424. g_stAdminPagePassword = value_string;
  425. }
  426.  
  427. TOKEN("hostname")
  428. {
  429. g_stHostname = value_string;
  430. fprintf(stdout, "HOSTNAME: %s\n", g_stHostname.c_str());
  431. continue;
  432. }
  433.  
  434. TOKEN("channel")
  435. {
  436. str_to_number(g_bChannel, value_string);
  437. continue;
  438. }
  439.  
  440. TOKEN("player_sql")
  441. {
  442. const char * line = two_arguments(value_string, db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
  443. line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
  444.  
  445. if (NULL != line[0])
  446. {
  447. char buf[256];
  448. one_argument(line, buf, sizeof(buf));
  449. str_to_number(mysql_db_port[0], buf);
  450. }
  451.  
  452. if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
  453. {
  454. fprintf(stderr, "PLAYER_SQL syntax: logsql <host user password db>\n");
  455. exit(1);
  456. }
  457.  
  458. char buf[1024];
  459. snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[0], db_user[0], db_pwd[0], db_db[0], mysql_db_port[0]);
  460. isPlayerSQL = true;
  461. continue;
  462. }
  463.  
  464. TOKEN("common_sql")
  465. {
  466. const char * line = two_arguments(value_string, db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
  467. line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
  468.  
  469. if (NULL != line[0])
  470. {
  471. char buf[256];
  472. one_argument(line, buf, sizeof(buf));
  473. str_to_number(mysql_db_port[1], buf);
  474. }
  475.  
  476. if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
  477. {
  478. fprintf(stderr, "COMMON_SQL syntax: logsql <host user password db>\n");
  479. exit(1);
  480. }
  481.  
  482. char buf[1024];
  483. snprintf(buf, sizeof(buf), "COMMON_SQL: %s %s %s %s %d", db_host[1], db_user[1], db_pwd[1], db_db[1], mysql_db_port[1]);
  484. isCommonSQL = true;
  485. continue;
  486. }
  487.  
  488. TOKEN("log_sql")
  489. {
  490. const char * line = two_arguments(value_string, log_host, sizeof(log_host), log_user, sizeof(log_user));
  491. line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
  492.  
  493. if (NULL != line[0])
  494. {
  495. char buf[256];
  496. one_argument(line, buf, sizeof(buf));
  497. str_to_number(log_port, buf);
  498. }
  499.  
  500. if (!*log_host || !*log_user || !*log_pwd || !*log_db)
  501. {
  502. fprintf(stderr, "LOG_SQL syntax: logsql <host user password db>\n");
  503. exit(1);
  504. }
  505.  
  506. char buf[1024];
  507. snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
  508. continue;
  509. }
  510.  
  511.  
  512. //OPENID
  513. TOKEN("WEB_AUTH")
  514. {
  515. const char * line = two_arguments(value_string, openid_host, sizeof(openid_host), openid_uri, sizeof(openid_uri));
  516.  
  517. if (!*openid_host || !*openid_uri)
  518. {
  519. fprintf(stderr, "WEB_AUTH syntax error (ex: WEB_AUTH <host(metin2.co.kr) uri(/kyw/gameauth.php)>\n");
  520. exit(1);
  521. }
  522.  
  523. char buf[1024];
  524. openid_server = 1;
  525. snprintf(buf, sizeof(buf), "WEB_AUTH: %s %s", openid_host, openid_uri);
  526. continue;
  527. }
  528. }
  529.  
  530. //󸮰¡ ³¡³µÀ¸´Ï ÆÄÀÏÀ» ´ÝÀÚ.
  531. fclose(fpOnlyForDB);
  532.  
  533. // CONFIG_SQL_INFO_ERROR
  534. if (!isCommonSQL)
  535. {
  536. puts("LOAD_COMMON_SQL_INFO_FAILURE:");
  537. puts("");
  538. puts("CONFIG:");
  539. puts("------------------------------------------------");
  540. puts("COMMON_SQL: HOST USER PASSWORD DATABASE");
  541. puts("");
  542. exit(1);
  543. }
  544.  
  545. if (!isPlayerSQL)
  546. {
  547. puts("LOAD_PLAYER_SQL_INFO_FAILURE:");
  548. puts("");
  549. puts("CONFIG:");
  550. puts("------------------------------------------------");
  551. puts("PLAYER_SQL: HOST USER PASSWORD DATABASE");
  552. puts("");
  553. exit(1);
  554. }
  555.  
  556. // Common DB °¡ Locale Á¤º¸¸¦ °¡Áö°í Àֱ⠶§¹®¿¡ °¡Àå ¸ÕÀú Á¢¼ÓÇØ¾ß ÇÑ´Ù.
  557. AccountDB::instance().Connect(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1]);
  558.  
  559. if (false == AccountDB::instance().IsConnected())
  560. {
  561. fprintf(stderr, "cannot start server while no common sql connected\n");
  562. exit(1);
  563. }
  564.  
  565. fprintf(stdout, "CommonSQL connected\n");
  566.  
  567. // ·ÎÄÉÀÏ Á¤º¸¸¦ °¡Á®¿ÀÀÚ
  568. // <°æ°í> Äõ¸®¹®¿¡ Àý´ë Á¶°Ç¹®(WHERE) ´ÞÁö ¸¶¼¼¿ä. (´Ù¸¥ Áö¿ª¿¡¼­ ¹®Á¦°¡ »ý±æ¼ö ÀÖ½À´Ï´Ù)
  569. {
  570. char szQuery[512];
  571. snprintf(szQuery, sizeof(szQuery), "SELECT mKey, mValue FROM locale");
  572.  
  573. std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  574.  
  575. if (pMsg->Get()->uiNumRows == 0)
  576. {
  577. fprintf(stderr, "COMMON_SQL: DirectQuery failed : %s\n", szQuery);
  578. exit(1);
  579. }
  580.  
  581. MYSQL_ROW row;
  582.  
  583. while (NULL != (row = mysql_fetch_row(pMsg->Get()->pSQLResult)))
  584. {
  585. // ·ÎÄÉÀÏ ¼¼ÆÃ
  586. if (strcasecmp(row[0], "LOCALE") == 0)
  587. {
  588. if (LocaleService_Init(row[1]) == false)
  589. {
  590. fprintf(stderr, "COMMON_SQL: invalid locale key %s\n", row[1]);
  591. exit(1);
  592. }
  593. }
  594. }
  595. }
  596.  
  597. // ·ÎÄÉÀÏ Á¤º¸¸¦ COMMON SQL¿¡ ¼¼ÆÃÇØÁØ´Ù.
  598. // Âü°í·Î g_stLocale Á¤º¸´Â LocaleService_Init() ³»ºÎ¿¡¼­ ¼¼ÆõȴÙ.
  599. fprintf(stdout, "Setting DB to locale %s\n", g_stLocale.c_str());
  600.  
  601. AccountDB::instance().SetLocale(g_stLocale);
  602.  
  603. AccountDB::instance().ConnectAsync(db_host[1], mysql_db_port[1], db_user[1], db_pwd[1], db_db[1], g_stLocale.c_str());
  604.  
  605. // Player DB Á¢¼Ó
  606. DBManager::instance().Connect(db_host[0], mysql_db_port[0], db_user[0], db_pwd[0], db_db[0]);
  607.  
  608. if (!DBManager::instance().IsConnected())
  609. {
  610. fprintf(stderr, "PlayerSQL.ConnectError\n");
  611. exit(1);
  612. }
  613.  
  614. fprintf(stdout, "PlayerSQL connected\n");
  615.  
  616. if (false == g_bAuthServer) // ÀÎÁõ ¼­¹ö°¡ ¾Æ´Ò °æ¿ì
  617. {
  618. // Log DB Á¢¼Ó
  619. LogManager::instance().Connect(log_host, log_port, log_user, log_pwd, log_db);
  620.  
  621. if (!LogManager::instance().IsConnected())
  622. {
  623. fprintf(stderr, "LogSQL.ConnectError\n");
  624. exit(1);
  625. }
  626.  
  627. fprintf(stdout, "LogSQL connected\n");
  628.  
  629. LogManager::instance().BootLog(g_stHostname.c_str(), g_bChannel);
  630. }
  631.  
  632. // SKILL_POWER_BY_LEVEL
  633. // ½ºÆ®¸µ ºñ±³ÀÇ ¹®Á¦·Î ÀÎÇؼ­ AccountDB::instance().SetLocale(g_stLocale) ÈĺÎÅÍ ÇÑ´Ù.
  634. // ¹°·Ð ±¹³»´Â º°·Î ¹®Á¦°¡ ¾ÈµÈ´Ù(ÇØ¿Ü°¡ ¹®Á¦)
  635. {
  636. char szQuery[256];
  637. snprintf(szQuery, sizeof(szQuery), "SELECT mValue FROM locale WHERE mKey='SKILL_POWER_BY_LEVEL'");
  638. std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  639.  
  640. if (pMsg->Get()->uiNumRows == 0)
  641. {
  642. fprintf(stderr, "[SKILL_PERCENT] Query failed: %s", szQuery);
  643. exit(1);
  644. }
  645.  
  646. MYSQL_ROW row;
  647.  
  648. row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  649.  
  650. const char * p = row[0];
  651. int cnt = 0;
  652. char num[128];
  653. int aiBaseSkillPowerByLevelTable[SKILL_MAX_LEVEL+1];
  654.  
  655. fprintf(stdout, "SKILL_POWER_BY_LEVEL %s\n", p);
  656. while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
  657. {
  658. p = one_argument(p, num, sizeof(num));
  659. aiBaseSkillPowerByLevelTable[cnt++] = atoi(num);
  660.  
  661. //fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
  662. if (*p == '\0')
  663. {
  664. if (cnt != (SKILL_MAX_LEVEL + 1))
  665. {
  666. fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
  667. exit(1);
  668. }
  669.  
  670. fprintf(stdout, "SKILL_POWER_BY_LEVEL: Done! (count %d)\n", cnt);
  671. break;
  672. }
  673. }
  674.  
  675. // Á¾Á·º° ½ºÅ³ ¼¼ÆÃ
  676. for (int job = 0; job < JOB_MAX_NUM * 2; ++job)
  677. {
  678. snprintf(szQuery, sizeof(szQuery), "SELECT mValue from locale where mKey='SKILL_POWER_BY_LEVEL_TYPE%d' ORDER BY CAST(mValue AS unsigned)", job);
  679. std::auto_ptr<SQLMsg> pMsg(AccountDB::instance().DirectQuery(szQuery));
  680.  
  681. // ¼¼ÆÃÀÌ ¾ÈµÇ¾îÀÖÀ¸¸é ±âº»Å×À̺íÀ» »ç¿ëÇÑ´Ù.
  682. if (pMsg->Get()->uiNumRows == 0)
  683. {
  684. CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiBaseSkillPowerByLevelTable);
  685. continue;
  686. }
  687.  
  688. row = mysql_fetch_row(pMsg->Get()->pSQLResult);
  689. cnt = 0;
  690. p = row[0];
  691. int aiSkillTable[SKILL_MAX_LEVEL + 1];
  692.  
  693. fprintf(stdout, "SKILL_POWER_BY_JOB %d %s\n", job, p);
  694. while (*p != '\0' && cnt < (SKILL_MAX_LEVEL + 1))
  695. {
  696. p = one_argument(p, num, sizeof(num));
  697. aiSkillTable[cnt++] = atoi(num);
  698.  
  699. //fprintf(stdout, "%d %d\n", cnt - 1, aiBaseSkillPowerByLevelTable[cnt - 1]);
  700. if (*p == '\0')
  701. {
  702. if (cnt != (SKILL_MAX_LEVEL + 1))
  703. {
  704. fprintf(stderr, "[SKILL_PERCENT] locale table has not enough skill information! (count: %d query: %s)", cnt, szQuery);
  705. exit(1);
  706. }
  707.  
  708. fprintf(stdout, "SKILL_POWER_BY_JOB: Done! (job: %d count: %d)\n", job, cnt);
  709. break;
  710. }
  711. }
  712.  
  713. CTableBySkill::instance().SetSkillPowerByLevelFromType(job, aiSkillTable);
  714. }
  715. }
  716. // END_SKILL_POWER_BY_LEVEL
  717.  
  718. // LOG_KEEP_DAYS_EXTEND
  719. log_set_expiration_days(2);
  720. // END_OF_LOG_KEEP_DAYS_EXTEND
  721.  
  722. while (fgets(buf, 256, fp))
  723. {
  724. parse_token(buf, token_string, value_string);
  725.  
  726. TOKEN("empire_whisper")
  727. {
  728. bool b_value = 0;
  729. str_to_number(b_value, value_string);
  730. g_bEmpireWhisper = !!b_value;
  731. continue;
  732. }
  733.  
  734. TOKEN("mark_server")
  735. {
  736. guild_mark_server = is_string_true(value_string);
  737. continue;
  738. }
  739.  
  740. TOKEN("mark_min_level")
  741. {
  742. str_to_number(guild_mark_min_level, value_string);
  743. guild_mark_min_level = MINMAX(0, guild_mark_min_level, GUILD_MAX_LEVEL);
  744. continue;
  745. }
  746.  
  747. TOKEN("port")
  748. {
  749. str_to_number(mother_port, value_string);
  750. continue;
  751. }
  752.  
  753. TOKEN("log_keep_days")
  754. {
  755. int i = 0;
  756. str_to_number(i, value_string);
  757. log_set_expiration_days(MINMAX(1, i, 90));
  758. continue;
  759. }
  760.  
  761. TOKEN("passes_per_sec")
  762. {
  763. str_to_number(passes_per_sec, value_string);
  764. continue;
  765. }
  766.  
  767. TOKEN("p2p_port")
  768. {
  769. str_to_number(p2p_port, value_string);
  770. continue;
  771. }
  772.  
  773. TOKEN("db_port")
  774. {
  775. str_to_number(db_port, value_string);
  776. continue;
  777. }
  778.  
  779. TOKEN("db_addr")
  780. {
  781. strlcpy(db_addr, value_string, sizeof(db_addr));
  782.  
  783. for (int n =0; n < ADDRESS_MAX_LEN; ++n)
  784. {
  785. if (db_addr[n] == ' ')
  786. db_addr[n] = '\0';
  787. }
  788.  
  789. continue;
  790. }
  791.  
  792. TOKEN("save_event_second_cycle")
  793. {
  794. int cycle = 0;
  795. str_to_number(cycle, value_string);
  796. save_event_second_cycle = cycle * passes_per_sec;
  797. continue;
  798. }
  799.  
  800. TOKEN("ping_event_second_cycle")
  801. {
  802. int cycle = 0;
  803. str_to_number(cycle, value_string);
  804. ping_event_second_cycle = cycle * passes_per_sec;
  805. continue;
  806. }
  807.  
  808. TOKEN("table_postfix")
  809. {
  810. g_table_postfix = value_string;
  811. continue;
  812. }
  813.  
  814. TOKEN("test_server")
  815. {
  816. printf("-----------------------------------------------\n");
  817. printf("TEST_SERVER\n");
  818. printf("-----------------------------------------------\n");
  819. str_to_number(test_server, value_string);
  820. continue;
  821. }
  822.  
  823. TOKEN("speed_server")
  824. {
  825. printf("-----------------------------------------------\n");
  826. printf("SPEED_SERVER\n");
  827. printf("-----------------------------------------------\n");
  828. str_to_number(speed_server, value_string);
  829. continue;
  830. }
  831. #ifdef __AUCTION__
  832. TOKEN("auction_server")
  833. {
  834. printf("-----------------------------------------------\n");
  835. printf("AUCTION_SERVER\n");
  836. printf("-----------------------------------------------\n");
  837. str_to_number(auction_server, value_string);
  838. continue;
  839. }
  840. #endif
  841. TOKEN("distribution_test_server")
  842. {
  843. str_to_number(distribution_test_server, value_string);
  844. continue;
  845. }
  846.  
  847. TOKEN("china_event_server")
  848. {
  849. str_to_number(china_event_server, value_string);
  850. continue;
  851. }
  852.  
  853. TOKEN("shutdowned")
  854. {
  855. g_bNoMoreClient = true;
  856. continue;
  857. }
  858.  
  859. TOKEN("no_regen")
  860. {
  861. g_bNoRegen = true;
  862. continue;
  863. }
  864.  
  865. TOKEN("traffic_profile")
  866. {
  867. g_bTrafficProfileOn = true;
  868. continue;
  869. }
  870.  
  871.  
  872. TOKEN("map_allow")
  873. {
  874. char * p = value_string;
  875. string stNum;
  876.  
  877. for (; *p; p++)
  878. {
  879. if (isnhspace(*p))
  880. {
  881. if (stNum.length())
  882. {
  883. int index = 0;
  884. str_to_number(index, stNum.c_str());
  885. map_allow_add(index);
  886. stNum.clear();
  887. }
  888. }
  889. else
  890. stNum += *p;
  891. }
  892.  
  893. if (stNum.length())
  894. {
  895. int index = 0;
  896. str_to_number(index, stNum.c_str());
  897. map_allow_add(index);
  898. }
  899.  
  900. continue;
  901. }
  902.  
  903. TOKEN("disable_rankdown_for_map")
  904. {
  905. char * p = value_string;
  906. string stNum;
  907.  
  908. for (; *p; p++)
  909. {
  910. if (isnhspace(*p))
  911. {
  912. if (stNum.length())
  913. {
  914. int index = 0;
  915. str_to_number(index, stNum.c_str());
  916. addMap(index);
  917. stNum.clear();
  918. }
  919. }
  920. else
  921. stNum += *p;
  922. }
  923.  
  924. if (stNum.length())
  925. {
  926. int index = 0;
  927. str_to_number(index, stNum.c_str());
  928. addMap(index);
  929. }
  930.  
  931. continue;
  932. }
  933.  
  934. TOKEN("no_wander")
  935. {
  936. no_wander = true;
  937. continue;
  938. }
  939.  
  940. TOKEN("user_limit")
  941. {
  942. str_to_number(g_iUserLimit, value_string);
  943. continue;
  944. }
  945.  
  946. TOKEN("skill_disable")
  947. {
  948. str_to_number(g_bSkillDisable, value_string);
  949. continue;
  950. }
  951.  
  952. TOKEN("auth_server")
  953. {
  954. char szIP[32];
  955. char szPort[32];
  956.  
  957. two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort));
  958.  
  959. if (!*szIP || (!*szPort && strcasecmp(szIP, "master")))
  960. {
  961. fprintf(stderr, "AUTH_SERVER: syntax error: <ip|master> <port>\n");
  962. exit(1);
  963. }
  964.  
  965. g_bAuthServer = true;
  966.  
  967. LoadBanIP("BANIP");
  968.  
  969. if (!strcasecmp(szIP, "master"))
  970. fprintf(stdout, "AUTH_SERVER: I am the master\n");
  971. else
  972. {
  973. g_stAuthMasterIP = szIP;
  974. str_to_number(g_wAuthMasterPort, szPort);
  975.  
  976. fprintf(stdout, "AUTH_SERVER: master %s %u\n", g_stAuthMasterIP.c_str(), g_wAuthMasterPort);
  977. }
  978. continue;
  979. }
  980.  
  981. TOKEN("billing")
  982. {
  983. g_bBilling = true;
  984. }
  985.  
  986. TOKEN("quest_dir")
  987. {
  988. sys_log(0, "QUEST_DIR SETTING : %s", value_string);
  989. g_stQuestDir = value_string;
  990. }
  991.  
  992. TOKEN("quest_object_dir")
  993. {
  994. //g_stQuestObjectDir = value_string;
  995. std::istringstream is(value_string);
  996. sys_log(0, "QUEST_OBJECT_DIR SETTING : %s", value_string);
  997. string dir;
  998. while (!is.eof())
  999. {
  1000. is >> dir;
  1001. if (is.fail())
  1002. break;
  1003. g_setQuestObjectDir.insert(dir);
  1004. sys_log(0, "QUEST_OBJECT_DIR INSERT : %s", dir .c_str());
  1005. }
  1006. }
  1007.  
  1008. TOKEN("teen_addr")
  1009. {
  1010. strlcpy(teen_addr, value_string, sizeof(teen_addr));
  1011.  
  1012. for (int n =0; n < ADDRESS_MAX_LEN; ++n)
  1013. {
  1014. if (teen_addr[n] == ' ')
  1015. teen_addr[n] = '\0';
  1016. }
  1017.  
  1018. continue;
  1019. }
  1020.  
  1021. TOKEN("teen_port")
  1022. {
  1023. str_to_number(teen_port, value_string);
  1024. }
  1025.  
  1026. TOKEN("synchack_limit_count")
  1027. {
  1028. str_to_number(g_iSyncHackLimitCount, value_string);
  1029. }
  1030.  
  1031. TOKEN("speedhack_limit_count")
  1032. {
  1033. str_to_number(SPEEDHACK_LIMIT_COUNT, value_string);
  1034. }
  1035.  
  1036. TOKEN("speedhack_limit_bonus")
  1037. {
  1038. str_to_number(SPEEDHACK_LIMIT_BONUS, value_string);
  1039. }
  1040.  
  1041. TOKEN("server_id")
  1042. {
  1043. str_to_number(g_server_id, value_string);
  1044. }
  1045.  
  1046. TOKEN("mall_url")
  1047. {
  1048. g_strWebMallURL = value_string;
  1049. }
  1050.  
  1051. TOKEN("bind_ip")
  1052. {
  1053. strlcpy(g_szPublicIP, value_string, sizeof(g_szPublicIP));
  1054. }
  1055.  
  1056. TOKEN("view_range")
  1057. {
  1058. str_to_number(VIEW_RANGE, value_string);
  1059. }
  1060.  
  1061. TOKEN("spam_block_duration")
  1062. {
  1063. str_to_number(g_uiSpamBlockDuration, value_string);
  1064. }
  1065.  
  1066. TOKEN("spam_block_score")
  1067. {
  1068. str_to_number(g_uiSpamBlockScore, value_string);
  1069. g_uiSpamBlockScore = MAX(1, g_uiSpamBlockScore);
  1070. }
  1071.  
  1072. TOKEN("spam_block_reload_cycle")
  1073. {
  1074. str_to_number(g_uiSpamReloadCycle, value_string);
  1075. g_uiSpamReloadCycle = MAX(60, g_uiSpamReloadCycle); // ÃÖ¼Ò 1ºÐ
  1076. }
  1077.  
  1078. TOKEN("check_multihack")
  1079. {
  1080. str_to_number(g_bCheckMultiHack, value_string);
  1081. }
  1082.  
  1083. TOKEN("spam_block_max_level")
  1084. {
  1085. str_to_number(g_iSpamBlockMaxLevel, value_string);
  1086. }
  1087. TOKEN("protect_normal_player")
  1088. {
  1089. str_to_number(g_protectNormalPlayer, value_string);
  1090. }
  1091. TOKEN("notice_battle_zone")
  1092. {
  1093. str_to_number(g_noticeBattleZone, value_string);
  1094. }
  1095.  
  1096. TOKEN("hackshield_enable")
  1097. {
  1098. int flag = 0;
  1099.  
  1100. str_to_number(flag, value_string);
  1101.  
  1102. //if (1 == flag && LC_IsEurope() )
  1103. if (1 == flag)
  1104. {
  1105. isHackShieldEnable = true;
  1106. }
  1107. }
  1108.  
  1109. TOKEN("hackshield_first_check_time")
  1110. {
  1111. int secs = 30;
  1112. str_to_number(secs, value_string);
  1113.  
  1114. HackShield_FirstCheckWaitTime = passes_per_sec * secs;
  1115. }
  1116.  
  1117. TOKEN("hackshield_check_cycle_time")
  1118. {
  1119. int secs = 180;
  1120. str_to_number(secs, value_string);
  1121.  
  1122. HackShield_CheckCycleTime = passes_per_sec * secs;
  1123. }
  1124.  
  1125. TOKEN("xtrap_enable")
  1126. {
  1127. int flag = 0;
  1128. str_to_number(flag, value_string);
  1129.  
  1130. if (1 == flag )
  1131. {
  1132. bXTrapEnabled = true;
  1133. }
  1134. }
  1135.  
  1136. TOKEN("pk_protect_level")
  1137. {
  1138. str_to_number(PK_PROTECT_LEVEL, value_string);
  1139. fprintf(stderr, "PK_PROTECT_LEVEL: %d", PK_PROTECT_LEVEL);
  1140. }
  1141.  
  1142. TOKEN("max_level")
  1143. {
  1144. str_to_number(gPlayerMaxLevel, value_string);
  1145.  
  1146. gPlayerMaxLevel = MINMAX(1, gPlayerMaxLevel, PLAYER_MAX_LEVEL_CONST);
  1147.  
  1148. fprintf(stderr, "PLAYER_MAX_LEVEL: %d\n", gPlayerMaxLevel);
  1149. }
  1150.  
  1151. TOKEN("block_char_creation")
  1152. {
  1153. int tmp = 0;
  1154.  
  1155. str_to_number(tmp, value_string);
  1156.  
  1157. if (0 == tmp)
  1158. g_BlockCharCreation = false;
  1159. else
  1160. g_BlockCharCreation = true;
  1161.  
  1162. continue;
  1163. }
  1164. }
  1165.  
  1166. if (g_setQuestObjectDir.empty())
  1167. g_setQuestObjectDir.insert(g_stDefaultQuestObjectDir);
  1168.  
  1169. if (0 == db_port)
  1170. {
  1171. fprintf(stderr, "DB_PORT not configured\n");
  1172. exit(1);
  1173. }
  1174.  
  1175. if (0 == g_bChannel)
  1176. {
  1177. fprintf(stderr, "CHANNEL not configured\n");
  1178. exit(1);
  1179. }
  1180.  
  1181. if (g_stHostname.empty())
  1182. {
  1183. fprintf(stderr, "HOSTNAME must be configured.\n");
  1184. exit(1);
  1185. }
  1186.  
  1187. // LOCALE_SERVICE
  1188. LocaleService_LoadLocaleStringFile();
  1189. LocaleService_TransferDefaultSetting();
  1190. LocaleService_LoadEmpireTextConvertTables();
  1191. // END_OF_LOCALE_SERVICE
  1192.  
  1193. fclose(fp);
  1194.  
  1195. if ((fp = fopen("CMD", "r")))
  1196. {
  1197. while (fgets(buf, 256, fp))
  1198. {
  1199. char cmd[32], levelname[32];
  1200. int level;
  1201.  
  1202. two_arguments(buf, cmd, sizeof(cmd), levelname, sizeof(levelname));
  1203.  
  1204. if (!*cmd || !*levelname)
  1205. {
  1206. fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
  1207. exit(1);
  1208. }
  1209.  
  1210. if (!strcasecmp(levelname, "LOW_WIZARD"))
  1211. level = GM_LOW_WIZARD;
  1212. else if (!strcasecmp(levelname, "WIZARD"))
  1213. level = GM_WIZARD;
  1214. else if (!strcasecmp(levelname, "HIGH_WIZARD"))
  1215. level = GM_HIGH_WIZARD;
  1216. else if (!strcasecmp(levelname, "GOD"))
  1217. level = GM_GOD;
  1218. else if (!strcasecmp(levelname, "IMPLEMENTOR"))
  1219. level = GM_IMPLEMENTOR;
  1220. else if (!strcasecmp(levelname, "DISABLE"))
  1221. level = GM_IMPLEMENTOR + 1;
  1222. else
  1223. {
  1224. fprintf(stderr, "CMD syntax error: <cmd> <DISABLE | LOW_WIZARD | WIZARD | HIGH_WIZARD | GOD>\n");
  1225. exit(1);
  1226. }
  1227.  
  1228. interpreter_set_privilege(cmd, level);
  1229. }
  1230.  
  1231. fclose(fp);
  1232. }
  1233.  
  1234. LoadValidCRCList();
  1235. LoadStateUserCount();
  1236.  
  1237. CWarMapManager::instance().LoadWarMapInfo(NULL);
  1238.  
  1239. FN_log_adminpage();
  1240. }
  1241.  
  1242. const char* get_table_postfix()
  1243. {
  1244. return g_table_postfix.c_str();
  1245. }
  1246.  
  1247. void LoadValidCRCList()
  1248. {
  1249. s_set_dwProcessCRC.clear();
  1250. s_set_dwFileCRC.clear();
  1251.  
  1252. FILE * fp;
  1253. char buf[256];
  1254.  
  1255. if ((fp = fopen("CRC", "r")))
  1256. {
  1257. while (fgets(buf, 256, fp))
  1258. {
  1259. if (!*buf)
  1260. continue;
  1261.  
  1262. DWORD dwValidClientProcessCRC;
  1263. DWORD dwValidClientFileCRC;
  1264.  
  1265. sscanf(buf, " %u %u ", &dwValidClientProcessCRC, &dwValidClientFileCRC);
  1266.  
  1267. s_set_dwProcessCRC.insert(dwValidClientProcessCRC);
  1268. s_set_dwFileCRC.insert(dwValidClientFileCRC);
  1269.  
  1270. fprintf(stderr, "CLIENT_CRC: %u %u\n", dwValidClientProcessCRC, dwValidClientFileCRC);
  1271. }
  1272.  
  1273. fclose(fp);
  1274. }
  1275. }
  1276.  
  1277. bool LoadClientVersion()
  1278. {
  1279. FILE * fp = fopen("VERSION", "r");
  1280.  
  1281. if (!fp)
  1282. return false;
  1283.  
  1284. char buf[256];
  1285. fgets(buf, 256, fp);
  1286.  
  1287. char * p = strchr(buf, '\n');
  1288. if (p) *p = '\0';
  1289.  
  1290. fprintf(stderr, "VERSION: \"%s\"\n", buf);
  1291.  
  1292. g_stClientVersion = buf;
  1293. fclose(fp);
  1294. return true;
  1295. }
  1296.  
  1297. void CheckClientVersion()
  1298. {
  1299. if (LC_IsEurope())
  1300. {
  1301. g_bCheckClientVersion = true;
  1302. }
  1303. else
  1304. {
  1305. g_bCheckClientVersion = false;
  1306. }
  1307.  
  1308. const DESC_MANAGER::DESC_SET & set = DESC_MANAGER::instance().GetClientSet();
  1309. DESC_MANAGER::DESC_SET::const_iterator it = set.begin();
  1310.  
  1311. while (it != set.end())
  1312. {
  1313. LPDESC d = *(it++);
  1314.  
  1315. if (!d->GetCharacter())
  1316. continue;
  1317.  
  1318.  
  1319. int version = atoi(g_stClientVersion.c_str());
  1320. int date = atoi(d->GetClientVersion() );
  1321.  
  1322. //if (0 != g_stClientVersion.compare(d->GetClientVersion()) )
  1323. if (version > date)
  1324. {
  1325. d->GetCharacter()->ChatPacket(CHAT_TYPE_NOTICE, LC_TEXT("Ŭ¶óÀ̾ðÆ® ¹öÀüÀÌ Æ²·Á ·Î±×¾Æ¿ô µË´Ï´Ù. Á¤»óÀûÀ¸·Î ÆÐÄ¡ ÈÄ Á¢¼ÓÇϼ¼¿ä."));
  1326. d->DelayedDisconnect(10);
  1327. }
  1328. }
  1329. }
  1330.  
  1331. void LoadStateUserCount()
  1332. {
  1333. FILE * fp = fopen("state_user_count", "r");
  1334.  
  1335. if (!fp)
  1336. return;
  1337.  
  1338. if (!LC_IsHongKong())
  1339. fscanf(fp, " %d %d ", &g_iFullUserCount, &g_iBusyUserCount);
  1340.  
  1341. fclose(fp);
  1342. }
  1343.  
  1344. bool IsValidProcessCRC(DWORD dwCRC)
  1345. {
  1346. return s_set_dwProcessCRC.find(dwCRC) != s_set_dwProcessCRC.end();
  1347. }
  1348.  
  1349. bool IsValidFileCRC(DWORD dwCRC)
  1350. {
  1351. return s_set_dwFileCRC.find(dwCRC) != s_set_dwFileCRC.end();
  1352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement