inter.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. // Copyright (c) rAthena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include "inter.hpp"
  4. #include <memory>
  5. #include <unordered_map>
  6. #include <vector>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <string>
  10. #include <sys/stat.h> // for stat/lstat/fstat - [Dekamaster/Ultimate GM Tool]
  11. #include "../common/cbasetypes.hpp"
  12. #include "../common/database.hpp"
  13. #include "../common/malloc.hpp"
  14. #include "../common/showmsg.hpp"
  15. #include "../common/socket.hpp"
  16. #include "../common/strlib.hpp"
  17. #include "../common/timer.hpp"
  18. #include "char.hpp"
  19. #include "char_logif.hpp"
  20. #include "char_mapif.hpp"
  21. #include "inter.hpp"
  22. #include "int_achievement.hpp"
  23. #include "int_auction.hpp"
  24. #include "int_clan.hpp"
  25. #include "int_elemental.hpp"
  26. #include "int_guild.hpp"
  27. #include "int_homun.hpp"
  28. #include "int_mail.hpp"
  29. #include "int_mercenary.hpp"
  30. #include "int_party.hpp"
  31. #include "int_pet.hpp"
  32. #include "int_quest.hpp"
  33. #include "int_storage.hpp"
  34. using namespace rathena;
  35. std::string cfgFile = "inter_athena.yml"; ///< Inter-Config file
  36. InterServerDatabase interServerDb;
  37. #define WISDATA_TTL (60*1000) //Wis data Time To Live (60 seconds)
  38. Sql* sql_handle = NULL; ///Link to mysql db, connection FD
  39. int char_server_port = 3306;
  40. std::string char_server_ip = "127.0.0.1";
  41. std::string char_server_id = "ragnarok";
  42. std::string char_server_pw = ""; // Allow user to send empty password (bugreport:7787)
  43. std::string char_server_db = "ragnarok";
  44. std::string default_codepage = ""; //Feature by irmin.
  45. unsigned int party_share_level = 10;
  46. /// Received packet Lengths from map-server
  47. int inter_recv_packet_length[] = {
  48. -1,-1, 7,-1, -1,13,36, (2+4+4+4+1+NAME_LENGTH), 0,-1, 0, 0, 0, 0, 0, 0, // 3000-
  49. 6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, // 3010-
  50. -1,10,-1,14, 15+NAME_LENGTH,17+MAP_NAME_LENGTH_EXT, 6,-1, 14,14, 6, 0, 0, 0, 0, 0, // 3020- Party
  51. -1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 18,19,186,-1, // 3030-
  52. -1, 9,10, 0, 0, 0, 0, 0, 8, 6,11,10, 10,-1,6+NAME_LENGTH, 0, // 3040-
  53. -1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus]
  54. 6,-1, 6,-1, 16+NAME_LENGTH+ACHIEVEMENT_NAME_LENGTH, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish] / Achievements [Aleos]
  55. -1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
  56. 52,14,-1, 6, 0, 0, 0, 0, 0, 0,13,-1, 0, 0, 0, 0, // 3080- Pet System, Storage
  57. -1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
  58. 2,-1, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30A0- Clan packets
  59. };
  60. #ifndef WHISPER_MESSAGE_SIZE
  61. #define WHISPER_MESSAGE_SIZE 512
  62. #endif
  63. struct WisData {
  64. int id, fd, count, len, gmlvl;
  65. t_tick tick;
  66. char src[NAME_LENGTH], dst[NAME_LENGTH], msg[WHISPER_MESSAGE_SIZE];
  67. };
  68. // int wis_id -> struct WisData*
  69. static std::unordered_map<int32, std::shared_ptr<struct WisData>> wis_db;
  70. /* from pc.cpp due to @accinfo. any ideas to replace this crap are more than welcome. */
  71. const char* job_name(int class_) {
  72. switch (class_) {
  73. case JOB_NOVICE:
  74. case JOB_SWORDMAN:
  75. case JOB_MAGE:
  76. case JOB_ARCHER:
  77. case JOB_ACOLYTE:
  78. case JOB_MERCHANT:
  79. case JOB_THIEF:
  80. return msg_txt(JOB_NOVICE+class_);
  81. case JOB_KNIGHT:
  82. case JOB_PRIEST:
  83. case JOB_WIZARD:
  84. case JOB_BLACKSMITH:
  85. case JOB_HUNTER:
  86. case JOB_ASSASSIN:
  87. return msg_txt(7 - JOB_KNIGHT+class_);
  88. case JOB_KNIGHT2:
  89. return msg_txt(7);
  90. case JOB_CRUSADER:
  91. case JOB_MONK:
  92. case JOB_SAGE:
  93. case JOB_ROGUE:
  94. case JOB_ALCHEMIST:
  95. case JOB_BARD:
  96. case JOB_DANCER:
  97. return msg_txt(13 - JOB_CRUSADER+class_);
  98. case JOB_CRUSADER2:
  99. return msg_txt(13);
  100. case JOB_WEDDING:
  101. case JOB_SUPER_NOVICE:
  102. case JOB_GUNSLINGER:
  103. case JOB_NINJA:
  104. case JOB_XMAS:
  105. return msg_txt(20 - JOB_WEDDING+class_);
  106. case JOB_SUMMER:
  107. case JOB_SUMMER2:
  108. return msg_txt(71);
  109. case JOB_HANBOK:
  110. case JOB_OKTOBERFEST:
  111. return msg_txt(105 - JOB_HANBOK+class_);
  112. case JOB_NOVICE_HIGH:
  113. case JOB_SWORDMAN_HIGH:
  114. case JOB_MAGE_HIGH:
  115. case JOB_ARCHER_HIGH:
  116. case JOB_ACOLYTE_HIGH:
  117. case JOB_MERCHANT_HIGH:
  118. case JOB_THIEF_HIGH:
  119. return msg_txt(25 - JOB_NOVICE_HIGH+class_);
  120. case JOB_LORD_KNIGHT:
  121. case JOB_HIGH_PRIEST:
  122. case JOB_HIGH_WIZARD:
  123. case JOB_WHITESMITH:
  124. case JOB_SNIPER:
  125. case JOB_ASSASSIN_CROSS:
  126. return msg_txt(32 - JOB_LORD_KNIGHT+class_);
  127. case JOB_LORD_KNIGHT2:
  128. return msg_txt(32);
  129. case JOB_PALADIN:
  130. case JOB_CHAMPION:
  131. case JOB_PROFESSOR:
  132. case JOB_STALKER:
  133. case JOB_CREATOR:
  134. case JOB_CLOWN:
  135. case JOB_GYPSY:
  136. return msg_txt(38 - JOB_PALADIN + class_);
  137. case JOB_PALADIN2:
  138. return msg_txt(38);
  139. case JOB_BABY:
  140. case JOB_BABY_SWORDMAN:
  141. case JOB_BABY_MAGE:
  142. case JOB_BABY_ARCHER:
  143. case JOB_BABY_ACOLYTE:
  144. case JOB_BABY_MERCHANT:
  145. case JOB_BABY_THIEF:
  146. return msg_txt(45 - JOB_BABY + class_);
  147. case JOB_BABY_KNIGHT:
  148. case JOB_BABY_PRIEST:
  149. case JOB_BABY_WIZARD:
  150. case JOB_BABY_BLACKSMITH:
  151. case JOB_BABY_HUNTER:
  152. case JOB_BABY_ASSASSIN:
  153. return msg_txt(52 - JOB_BABY_KNIGHT + class_);
  154. case JOB_BABY_KNIGHT2:
  155. return msg_txt(52);
  156. case JOB_BABY_CRUSADER:
  157. case JOB_BABY_MONK:
  158. case JOB_BABY_SAGE:
  159. case JOB_BABY_ROGUE:
  160. case JOB_BABY_ALCHEMIST:
  161. case JOB_BABY_BARD:
  162. case JOB_BABY_DANCER:
  163. return msg_txt(58 - JOB_BABY_CRUSADER + class_);
  164. case JOB_BABY_CRUSADER2:
  165. return msg_txt(58);
  166. case JOB_SUPER_BABY:
  167. return msg_txt(65);
  168. case JOB_TAEKWON:
  169. return msg_txt(66);
  170. case JOB_STAR_GLADIATOR:
  171. case JOB_STAR_GLADIATOR2:
  172. return msg_txt(67);
  173. case JOB_SOUL_LINKER:
  174. return msg_txt(68);
  175. case JOB_GANGSI:
  176. case JOB_DEATH_KNIGHT:
  177. case JOB_DARK_COLLECTOR:
  178. return msg_txt(72 - JOB_GANGSI+class_);
  179. case JOB_RUNE_KNIGHT:
  180. case JOB_WARLOCK:
  181. case JOB_RANGER:
  182. case JOB_ARCH_BISHOP:
  183. case JOB_MECHANIC:
  184. case JOB_GUILLOTINE_CROSS:
  185. return msg_txt(75 - JOB_RUNE_KNIGHT+class_);
  186. case JOB_RUNE_KNIGHT_T:
  187. case JOB_WARLOCK_T:
  188. case JOB_RANGER_T:
  189. case JOB_ARCH_BISHOP_T:
  190. case JOB_MECHANIC_T:
  191. case JOB_GUILLOTINE_CROSS_T:
  192. return msg_txt(75 - JOB_RUNE_KNIGHT_T+class_);
  193. case JOB_ROYAL_GUARD:
  194. case JOB_SORCERER:
  195. case JOB_MINSTREL:
  196. case JOB_WANDERER:
  197. case JOB_SURA:
  198. case JOB_GENETIC:
  199. case JOB_SHADOW_CHASER:
  200. return msg_txt(81 - JOB_ROYAL_GUARD+class_);
  201. case JOB_ROYAL_GUARD_T:
  202. case JOB_SORCERER_T:
  203. case JOB_MINSTREL_T:
  204. case JOB_WANDERER_T:
  205. case JOB_SURA_T:
  206. case JOB_GENETIC_T:
  207. case JOB_SHADOW_CHASER_T:
  208. return msg_txt(81 - JOB_ROYAL_GUARD_T+class_);
  209. case JOB_RUNE_KNIGHT2:
  210. case JOB_RUNE_KNIGHT_T2:
  211. return msg_txt(75);
  212. case JOB_ROYAL_GUARD2:
  213. case JOB_ROYAL_GUARD_T2:
  214. return msg_txt(81);
  215. case JOB_RANGER2:
  216. case JOB_RANGER_T2:
  217. return msg_txt(77);
  218. case JOB_MECHANIC2:
  219. case JOB_MECHANIC_T2:
  220. return msg_txt(79);
  221. case JOB_BABY_RUNE_KNIGHT:
  222. case JOB_BABY_WARLOCK:
  223. case JOB_BABY_RANGER:
  224. case JOB_BABY_ARCH_BISHOP:
  225. case JOB_BABY_MECHANIC:
  226. case JOB_BABY_GUILLOTINE_CROSS:
  227. case JOB_BABY_ROYAL_GUARD:
  228. case JOB_BABY_SORCERER:
  229. case JOB_BABY_MINSTREL:
  230. case JOB_BABY_WANDERER:
  231. case JOB_BABY_SURA:
  232. case JOB_BABY_GENETIC:
  233. case JOB_BABY_SHADOW_CHASER:
  234. return msg_txt(88 - JOB_BABY_RUNE_KNIGHT+class_);
  235. case JOB_BABY_RUNE_KNIGHT2:
  236. return msg_txt(88);
  237. case JOB_BABY_ROYAL_GUARD2:
  238. return msg_txt(94);
  239. case JOB_BABY_RANGER2:
  240. return msg_txt(90);
  241. case JOB_BABY_MECHANIC2:
  242. return msg_txt(92);
  243. case JOB_SUPER_NOVICE_E:
  244. case JOB_SUPER_BABY_E:
  245. return msg_txt(101 - JOB_SUPER_NOVICE_E+class_);
  246. case JOB_KAGEROU:
  247. case JOB_OBORO:
  248. return msg_txt(103 - JOB_KAGEROU+class_);
  249. case JOB_REBELLION:
  250. return msg_txt(106);
  251. case JOB_SUMMONER:
  252. return msg_txt(108);
  253. case JOB_BABY_SUMMONER:
  254. return msg_txt(109);
  255. case JOB_BABY_NINJA:
  256. case JOB_BABY_KAGEROU:
  257. case JOB_BABY_OBORO:
  258. case JOB_BABY_TAEKWON:
  259. case JOB_BABY_STAR_GLADIATOR:
  260. case JOB_BABY_SOUL_LINKER:
  261. case JOB_BABY_GUNSLINGER:
  262. case JOB_BABY_REBELLION:
  263. return msg_txt(110 - JOB_BABY_NINJA+class_);
  264. case JOB_BABY_STAR_GLADIATOR2:
  265. case JOB_STAR_EMPEROR:
  266. case JOB_SOUL_REAPER:
  267. case JOB_BABY_STAR_EMPEROR:
  268. case JOB_BABY_SOUL_REAPER:
  269. return msg_txt(114 - JOB_BABY_STAR_GLADIATOR2 + class_);
  270. case JOB_STAR_EMPEROR2:
  271. return msg_txt(118);
  272. case JOB_BABY_STAR_EMPEROR2:
  273. return msg_txt(120);
  274. case JOB_DRAGON_KNIGHT:
  275. case JOB_MEISTER:
  276. case JOB_SHADOW_CROSS:
  277. case JOB_ARCH_MAGE:
  278. case JOB_CARDINAL:
  279. case JOB_WINDHAWK:
  280. case JOB_IMPERIAL_GUARD:
  281. case JOB_BIOLO:
  282. case JOB_ABYSS_CHASER:
  283. case JOB_ELEMENTAL_MASTER:
  284. case JOB_INQUISITOR:
  285. case JOB_TROUBADOUR:
  286. case JOB_TROUVERE:
  287. return msg_txt( 122 - JOB_DRAGON_KNIGHT + class_ );
  288. case JOB_WINDHAWK2:
  289. return msg_txt( 127 );
  290. case JOB_MEISTER2:
  291. return msg_txt( 123 );
  292. case JOB_DRAGON_KNIGHT2:
  293. return msg_txt( 122 );
  294. case JOB_IMPERIAL_GUARD2:
  295. return msg_txt( 128 );
  296. case JOB_SKY_EMPEROR:
  297. case JOB_SOUL_ASCETIC:
  298. case JOB_SHINKIRO:
  299. case JOB_SHIRANUI:
  300. case JOB_NIGHT_WATCH:
  301. case JOB_HYPER_NOVICE:
  302. case JOB_SPIRIT_HANDLER:
  303. return msg_txt( 135 - JOB_SKY_EMPEROR + class_ );
  304. case JOB_SKY_EMPEROR2:
  305. return msg_txt( 135 );
  306. default:
  307. return msg_txt(199);
  308. }
  309. }
  310. /**
  311. * [Dekamaster/Nightroad]
  312. **/
  313. const char * geoip_countryname[253] = {"Unknown","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles",
  314. "Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados",
  315. "Bangladesh","Belgium","Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia",
  316. "Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the",
  317. "Central African Republic","Congo","Switzerland","Cote D'Ivoire","Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica",
  318. "Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic",
  319. "Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji",
  320. "Falkland Islands (Malvinas)","Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana",
  321. "Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala",
  322. "Guam","Guinea-Bissau","Guyana","Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia",
  323. "Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan",
  324. "Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis","Korea, Democratic People's Republic of","Korea, Republic of","Kuwait",
  325. "Cayman Islands","Kazakhstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania",
  326. "Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar","Marshall Islands","Macedonia","Mali",
  327. "Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives",
  328. "Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua",
  329. "Netherlands","Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia",
  330. "Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau",
  331. "Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia","Solomon Islands","Seychelles","Sudan",
  332. "Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname",
  333. "Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo","Thailand",
  334. "Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan",
  335. "Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines","Venezuela",
  336. "Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa",
  337. "Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider","Other","Aland Islands","Guernsey","Isle of Man","Jersey",
  338. "Saint Barthelemy","Saint Martin"};
  339. unsigned char *geoip_cache;
  340. void geoip_readdb(void){
  341. struct stat bufa;
  342. FILE *db=fopen("./db/GeoIP.dat","rb");
  343. fstat(fileno(db), &bufa);
  344. geoip_cache = (unsigned char *) aMalloc(sizeof(unsigned char) * bufa.st_size);
  345. if(fread(geoip_cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) { ShowError("geoip_cache reading didn't read all elements \n"); }
  346. fclose(db);
  347. ShowStatus("Finished Reading " CL_GREEN "GeoIP" CL_RESET " Database.\n");
  348. }
  349. /* [Dekamaster/Nightroad] */
  350. /* There are millions of entries in GeoIP and it has its own algorithm to go quickly through them */
  351. const char* geoip_getcountry(uint32 ipnum){
  352. int depth;
  353. unsigned int x;
  354. unsigned int offset = 0;
  355. for (depth = 31; depth >= 0; depth--) {
  356. const unsigned char *buf;
  357. buf = geoip_cache + (long)6 *offset;
  358. if (ipnum & (1 << depth)) {
  359. /* Take the right-hand branch */
  360. x = (buf[3*1 + 0] << (0*8))
  361. + (buf[3*1 + 1] << (1*8))
  362. + (buf[3*1 + 2] << (2*8));
  363. } else {
  364. /* Take the left-hand branch */
  365. x = (buf[3*0 + 0] << (0*8))
  366. + (buf[3*0 + 1] << (1*8))
  367. + (buf[3*0 + 2] << (2*8));
  368. }
  369. if (x >= 16776960) {
  370. x=x-16776960;
  371. return geoip_countryname[x];
  372. }
  373. offset = x;
  374. }
  375. return geoip_countryname[0];
  376. }
  377. /* sends a mesasge to map server (fd) to a user (u_fd) although we use fd we keep aid for safe-check */
  378. /* extremely handy I believe it will serve other uses in the near future */
  379. void inter_to_fd(int fd, int u_fd, int aid, char* msg, ...) {
  380. char msg_out[512];
  381. va_list ap;
  382. int len = 1;/* yes we start at 1 */
  383. va_start(ap,msg);
  384. len += vsnprintf(msg_out, 512, msg, ap);
  385. va_end(ap);
  386. WFIFOHEAD(fd,12 + len);
  387. WFIFOW(fd,0) = 0x3807;
  388. WFIFOW(fd,2) = 12 + (unsigned short)len;
  389. WFIFOL(fd,4) = u_fd;
  390. WFIFOL(fd,8) = aid;
  391. safestrncpy(WFIFOCP(fd,12), msg_out, len);
  392. WFIFOSET(fd,12 + len);
  393. return;
  394. }
  395. /**
  396. * Transmit the result of a account_information request from map-serv, with type 1
  397. * @param fd : map-serv link
  398. * @param u_fd : player fd to send info to
  399. * @param acc_id : id of player found
  400. * @param acc_name : name of player found
  401. */
  402. void mapif_acc_info_ack(int fd, int u_fd, int acc_id, const char* acc_name){
  403. WFIFOHEAD(fd,10 + NAME_LENGTH);
  404. WFIFOW(fd,0) = 0x3808;
  405. WFIFOL(fd,2) = u_fd;
  406. WFIFOL(fd,6) = acc_id;
  407. safestrncpy(WFIFOCP(fd,10),acc_name,NAME_LENGTH);
  408. WFIFOSET(fd,10 + NAME_LENGTH);
  409. }
  410. /**
  411. * Receive a account_info request from map-serv
  412. * @author : [Dekamaster/Nightroad]
  413. * @param fd : map-serv link
  414. */
  415. void mapif_parse_accinfo(int fd) {
  416. int u_fd = RFIFOL(fd,2), u_aid = RFIFOL(fd,6), u_group = RFIFOL(fd,10);
  417. char type= RFIFOB(fd,14);
  418. char query[NAME_LENGTH], query_esq[NAME_LENGTH*2+1];
  419. uint32 account_id = 0;
  420. char *data;
  421. safestrncpy(query, RFIFOCP(fd,15), NAME_LENGTH);
  422. Sql_EscapeString(sql_handle, query_esq, query);
  423. account_id = atoi(query);
  424. if (account_id < START_ACCOUNT_NUM) { // is string
  425. if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `%s` WHERE `name` LIKE '%s' LIMIT 10", schema_config.char_db, query_esq)
  426. || Sql_NumRows(sql_handle) == 0 ) {
  427. if( Sql_NumRows(sql_handle) == 0 ) {
  428. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(212) ,query);
  429. } else {
  430. Sql_ShowDebug(sql_handle);
  431. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
  432. }
  433. Sql_FreeResult(sql_handle);
  434. return;
  435. } else {
  436. if( Sql_NumRows(sql_handle) == 1 ) {//we found a perfect match
  437. Sql_NextRow(sql_handle);
  438. Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
  439. Sql_FreeResult(sql_handle);
  440. } else {// more than one, listing... [Dekamaster/Nightroad]
  441. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(214),(int)Sql_NumRows(sql_handle));
  442. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  443. int class_;
  444. short base_level, job_level, online;
  445. char name[NAME_LENGTH];
  446. Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data);
  447. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
  448. Sql_GetData(sql_handle, 2, &data, NULL); class_ = atoi(data);
  449. Sql_GetData(sql_handle, 3, &data, NULL); base_level = atoi(data);
  450. Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data);
  451. Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data);
  452. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(215), account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
  453. }
  454. Sql_FreeResult(sql_handle);
  455. return;
  456. }
  457. }
  458. }
  459. /* it will only get here if we have a single match then ask login-server to fetch the `login` record */
  460. if (!account_id || chlogif_req_accinfo(fd, u_fd, u_aid, account_id, type) != 1) {
  461. inter_to_fd(fd, u_fd, u_aid, (char *)msg_txt(213));
  462. }
  463. return;
  464. }
  465. /**
  466. * Show account info from login-server to user
  467. */
  468. void mapif_accinfo_ack(bool success, int map_fd, int u_fd, int u_aid, int account_id, int8 type,
  469. int group_id, int logincount, int state, const char *email, const char *last_ip, const char *lastlogin,
  470. const char *birthdate, const char *userid)
  471. {
  472. if (map_fd <= 0 || !session_isActive(map_fd))
  473. return; // check if we have a valid fd
  474. if (!success) {
  475. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(216), account_id);
  476. return;
  477. }
  478. if (type == 1) { //type 1 we don't want all the info [lighta] @CHECKME
  479. mapif_acc_info_ack(map_fd, u_fd, account_id, userid);
  480. return;
  481. }
  482. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(217), account_id);
  483. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(218), userid, group_id, state);
  484. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(221), email, birthdate);
  485. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(222), last_ip, geoip_getcountry(str2ip(last_ip)));
  486. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(223), logincount, lastlogin);
  487. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(224));
  488. if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `%s` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", schema_config.char_db, account_id, MAX_CHARS)
  489. || Sql_NumRows(sql_handle) == 0 )
  490. {
  491. if( Sql_NumRows(sql_handle) == 0 )
  492. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(226));
  493. else {
  494. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(213));
  495. Sql_ShowDebug(sql_handle);
  496. }
  497. } else {
  498. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  499. uint32 char_id, class_;
  500. short char_num, base_level, job_level, online;
  501. char name[NAME_LENGTH];
  502. char *data;
  503. Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data);
  504. Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name));
  505. Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data);
  506. Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data);
  507. Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data);
  508. Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data);
  509. Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data);
  510. inter_to_fd(map_fd, u_fd, u_aid, (char *)msg_txt(225), char_num, char_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline");
  511. }
  512. }
  513. Sql_FreeResult(sql_handle);
  514. }
  515. /**
  516. * Handles save reg data from map server and distributes accordingly.
  517. *
  518. * @param val either str or int, depending on type
  519. * @param type false when int, true otherwise
  520. **/
  521. void inter_savereg(uint32 account_id, uint32 char_id, const char *key, uint32 index, int64 int_value, const char* string_value, bool is_string)
  522. {
  523. char esc_val[254*2+1];
  524. char esc_key[32*2+1];
  525. Sql_EscapeString(sql_handle, esc_key, key);
  526. if( is_string && string_value ) {
  527. Sql_EscapeString(sql_handle, esc_val, string_value);
  528. }
  529. if( key[0] == '#' && key[1] == '#' ) { // global account reg
  530. if( session_isValid(login_fd) )
  531. chlogif_send_global_accreg( key, index, int_value, string_value, is_string );
  532. else {
  533. ShowError("Login server unavailable, can't perform update on '%s' variable for AID:%" PRIu32 " CID:%" PRIu32 "\n",key,account_id,char_id);
  534. }
  535. } else if ( key[0] == '#' ) { // local account reg
  536. if( is_string ) {
  537. if( string_value ) {
  538. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%s')", schema_config.acc_reg_str_table, account_id, esc_key, index, esc_val) )
  539. Sql_ShowDebug(sql_handle);
  540. } else {
  541. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.acc_reg_str_table, account_id, esc_key, index) )
  542. Sql_ShowDebug(sql_handle);
  543. }
  544. } else {
  545. if( int_value ) {
  546. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%" PRId64 "')", schema_config.acc_reg_num_table, account_id, esc_key, index, int_value) )
  547. Sql_ShowDebug(sql_handle);
  548. } else {
  549. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.acc_reg_num_table, account_id, esc_key, index) )
  550. Sql_ShowDebug(sql_handle);
  551. }
  552. }
  553. } else { /* char reg */
  554. if( is_string ) {
  555. if( string_value ) {
  556. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%s')", schema_config.char_reg_str_table, char_id, esc_key, index, esc_val) )
  557. Sql_ShowDebug(sql_handle);
  558. } else {
  559. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.char_reg_str_table, char_id, esc_key, index) )
  560. Sql_ShowDebug(sql_handle);
  561. }
  562. } else {
  563. if( int_value ) {
  564. if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`,`key`,`index`,`value`) VALUES ('%" PRIu32 "','%s','%" PRIu32 "','%" PRId64 "')", schema_config.char_reg_num_table, char_id, esc_key, index, int_value) )
  565. Sql_ShowDebug(sql_handle);
  566. } else {
  567. if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%" PRIu32 "' AND `key` = '%s' AND `index` = '%" PRIu32 "' LIMIT 1", schema_config.char_reg_num_table, char_id, esc_key, index) )
  568. Sql_ShowDebug(sql_handle);
  569. }
  570. }
  571. }
  572. }
  573. // Load account_reg from sql (type=2)
  574. int inter_accreg_fromsql(uint32 account_id, uint32 char_id, int fd, int type)
  575. {
  576. char* data;
  577. size_t len;
  578. unsigned int plen = 0;
  579. switch( type ) {
  580. case 3: //char reg
  581. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%" PRIu32 "'", schema_config.char_reg_str_table, char_id) )
  582. Sql_ShowDebug(sql_handle);
  583. break;
  584. case 2: //account reg
  585. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%" PRIu32 "'", schema_config.acc_reg_str_table, account_id) )
  586. Sql_ShowDebug(sql_handle);
  587. break;
  588. case 1: //account2 reg
  589. ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's job!\n");
  590. return 0;
  591. default:
  592. ShowError("inter_accreg_fromsql: Invalid type %d\n", type);
  593. return 0;
  594. }
  595. WFIFOHEAD(fd, 60000 + 300);
  596. WFIFOW(fd, 0) = 0x3804;
  597. // 0x2 = length, set prior to being sent
  598. WFIFOL(fd, 4) = account_id;
  599. WFIFOL(fd, 8) = char_id;
  600. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  601. WFIFOB(fd, 13) = 1; // is string type
  602. WFIFOW(fd, 14) = 0; // count
  603. plen = 16;
  604. /**
  605. * Vessel!
  606. *
  607. * str type
  608. * { keyLength(B), key(<keyLength>), index(L), valLength(B), val(<valLength>) }
  609. **/
  610. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  611. Sql_GetData(sql_handle, 0, &data, NULL);
  612. len = strlen(data)+1;
  613. WFIFOB(fd, plen) = (unsigned char)len; // won't be higher; the column size is 32
  614. plen += 1;
  615. safestrncpy(WFIFOCP(fd,plen), data, len);
  616. plen += len;
  617. Sql_GetData(sql_handle, 1, &data, NULL);
  618. WFIFOL(fd, plen) = (uint32)atol(data);
  619. plen += 4;
  620. Sql_GetData(sql_handle, 2, &data, NULL);
  621. len = strlen(data)+1;
  622. WFIFOB(fd, plen) = (unsigned char)len; // won't be higher; the column size is 254
  623. plen += 1;
  624. safestrncpy(WFIFOCP(fd,plen), data, len);
  625. plen += len;
  626. WFIFOW(fd, 14) += 1;
  627. if( plen > 60000 ) {
  628. WFIFOW(fd, 2) = plen;
  629. WFIFOSET(fd, plen);
  630. // prepare follow up
  631. WFIFOHEAD(fd, 60000 + 300);
  632. WFIFOW(fd, 0) = 0x3804;
  633. // 0x2 = length, set prior to being sent
  634. WFIFOL(fd, 4) = account_id;
  635. WFIFOL(fd, 8) = char_id;
  636. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  637. WFIFOB(fd, 13) = 1; // is string type
  638. WFIFOW(fd, 14) = 0; // count
  639. plen = 16;
  640. }
  641. }
  642. WFIFOW(fd, 2) = plen;
  643. WFIFOSET(fd, plen);
  644. Sql_FreeResult(sql_handle);
  645. switch( type ) {
  646. case 3: //char reg
  647. if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `char_id`='%" PRIu32 "'", schema_config.char_reg_num_table, char_id))
  648. Sql_ShowDebug(sql_handle);
  649. break;
  650. case 2: //account reg
  651. if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `key`, `index`, `value` FROM `%s` WHERE `account_id`='%" PRIu32 "'", schema_config.acc_reg_num_table, account_id))
  652. Sql_ShowDebug(sql_handle);
  653. break;
  654. #if 0 // This is already checked above.
  655. case 1: //account2 reg
  656. ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n");
  657. return 0;
  658. #endif // 0
  659. }
  660. WFIFOHEAD(fd, 60000 + 300);
  661. WFIFOW(fd, 0) = 0x3804;
  662. // 0x2 = length, set prior to being sent
  663. WFIFOL(fd, 4) = account_id;
  664. WFIFOL(fd, 8) = char_id;
  665. WFIFOB(fd, 12) = 0; // var type (only set when all vars have been sent, regardless of type)
  666. WFIFOB(fd, 13) = 0; // is int type
  667. WFIFOW(fd, 14) = 0; // count
  668. plen = 16;
  669. /**
  670. * Vessel!
  671. *
  672. * int type
  673. * { keyLength(B), key(<keyLength>), index(L), value(L) }
  674. **/
  675. while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) {
  676. Sql_GetData(sql_handle, 0, &data, NULL);
  677. len = strlen(data)+1;
  678. WFIFOB(fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */
  679. plen += 1;
  680. safestrncpy(WFIFOCP(fd,plen), data, len);
  681. plen += len;
  682. Sql_GetData(sql_handle, 1, &data, NULL);
  683. WFIFOL(fd, plen) = (uint32)atol(data);
  684. plen += 4;
  685. Sql_GetData(sql_handle, 2, &data, NULL);
  686. WFIFOQ(fd, plen) = strtoll(data,NULL,10);
  687. plen += 8;
  688. WFIFOW(fd, 14) += 1;
  689. if( plen > 60000 ) {
  690. WFIFOW(fd, 2) = plen;
  691. WFIFOSET(fd, plen);
  692. /* prepare follow up */
  693. WFIFOHEAD(fd, 60000 + 300);
  694. WFIFOW(fd, 0) = 0x3804;
  695. /* 0x2 = length, set prior to being sent */
  696. WFIFOL(fd, 4) = account_id;
  697. WFIFOL(fd, 8) = char_id;
  698. WFIFOB(fd, 12) = 0;/* var type (only set when all vars have been sent, regardless of type) */
  699. WFIFOB(fd, 13) = 0;/* is int type */
  700. WFIFOW(fd, 14) = 0;/* count */
  701. plen = 16;
  702. }
  703. }
  704. WFIFOB(fd, 12) = type;
  705. WFIFOW(fd, 2) = plen;
  706. WFIFOSET(fd, plen);
  707. Sql_FreeResult(sql_handle);
  708. return 1;
  709. }
  710. /*==========================================
  711. * read config file
  712. *------------------------------------------*/
  713. int inter_config_read(const char* cfgName)
  714. {
  715. char line[1024];
  716. FILE* fp;
  717. fp = fopen(cfgName, "r");
  718. if(fp == NULL) {
  719. ShowError("File not found: %s\n", cfgName);
  720. return 1;
  721. }
  722. while(fgets(line, sizeof(line), fp)) {
  723. char w1[24], w2[1024];
  724. if (line[0] == '/' && line[1] == '/')
  725. continue;
  726. if (sscanf(line, "%23[^:]: %1023[^\r\n]", w1, w2) != 2)
  727. continue;
  728. if(!strcmpi(w1,"char_server_ip"))
  729. char_server_ip = w2;
  730. else if(!strcmpi(w1,"char_server_port"))
  731. char_server_port = atoi(w2);
  732. else if(!strcmpi(w1,"char_server_id"))
  733. char_server_id = w2;
  734. else if(!strcmpi(w1,"char_server_pw"))
  735. char_server_pw = w2;
  736. else if(!strcmpi(w1,"char_server_db"))
  737. char_server_db = w2;
  738. else if(!strcmpi(w1,"default_codepage"))
  739. default_codepage = w2;
  740. else if(!strcmpi(w1,"party_share_level"))
  741. party_share_level = (unsigned int)atof(w2);
  742. else if(!strcmpi(w1,"log_inter"))
  743. charserv_config.log_inter = atoi(w2);
  744. else if(!strcmpi(w1,"inter_server_conf"))
  745. cfgFile = w2;
  746. else if(!strcmpi(w1,"import"))
  747. inter_config_read(w2);
  748. }
  749. fclose(fp);
  750. ShowInfo ("Done reading %s.\n", cfgName);
  751. return 0;
  752. }
  753. // Save interlog into sql
  754. int inter_log(const char* fmt, ...)
  755. {
  756. char str[255];
  757. char esc_str[sizeof(str)*2+1];// escaped str
  758. va_list ap;
  759. va_start(ap,fmt);
  760. vsnprintf(str, sizeof(str), fmt, ap);
  761. va_end(ap);
  762. Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str)));
  763. if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", schema_config.interlog_db, esc_str) )
  764. Sql_ShowDebug(sql_handle);
  765. return 0;
  766. }
  767. const std::string InterServerDatabase::getDefaultLocation(){
  768. return std::string(conf_path) + "/" + cfgFile;
  769. }
  770. /**
  771. * Reads and parses an entry from the inter_server.
  772. * @param node: YAML node containing the entry.
  773. * @return count of successfully parsed rows
  774. */
  775. uint64 InterServerDatabase::parseBodyNode( const ryml::NodeRef& node ){
  776. uint32 id;
  777. if( !this->asUInt32( node, "ID", id ) ){
  778. return 0;
  779. }
  780. auto storage_table = this->find( id );
  781. bool existing = storage_table != nullptr;
  782. if( !existing ){
  783. if( !this->nodeExists( node, "Name" ) ){
  784. this->invalidWarning( node, "Node \"Name\" is missing.\n" );
  785. return 0;
  786. }
  787. if( !this->nodeExists( node, "Table" ) ){
  788. this->invalidWarning( node, "Node \"Table\" is missing.\n" );
  789. return 0;
  790. }
  791. storage_table = std::make_shared<s_storage_table>();
  792. storage_table->id = (uint8)id;
  793. }
  794. if( this->nodeExists( node, "Name" ) ){
  795. std::string name;
  796. if( !this->asString( node, "Name", name ) ){
  797. return 0;
  798. }
  799. safestrncpy( storage_table->name, name.c_str(), NAME_LENGTH );
  800. }
  801. if( this->nodeExists( node, "Table" ) ){
  802. std::string table;
  803. if( !this->asString( node, "Table", table ) ){
  804. return 0;
  805. }
  806. safestrncpy( storage_table->table, table.c_str(), DB_NAME_LEN );
  807. }
  808. if( this->nodeExists( node, "Max" ) ){
  809. uint16 max;
  810. if( !this->asUInt16( node, "Max", max ) ){
  811. return 0;
  812. }
  813. storage_table->max_num = max;
  814. }else{
  815. if( !existing ){
  816. storage_table->max_num = MAX_STORAGE;
  817. }
  818. }
  819. if( !existing ){
  820. this->put( storage_table->id, storage_table );
  821. }
  822. return 1;
  823. }
  824. // initialize
  825. int inter_init_sql(const char *file)
  826. {
  827. inter_config_read(file);
  828. //DB connection initialized
  829. sql_handle = Sql_Malloc();
  830. ShowInfo("Connect Character DB server.... (Character Server)\n");
  831. if( SQL_ERROR == Sql_Connect(sql_handle, char_server_id.c_str(), char_server_pw.c_str(), char_server_ip.c_str(), (uint16)char_server_port, char_server_db.c_str()))
  832. {
  833. ShowError("Couldn't connect with username = '%s', host = '%s', port = '%d', database = '%s'\n",
  834. char_server_id.c_str(), char_server_ip.c_str(), char_server_port, char_server_db.c_str());
  835. Sql_ShowDebug(sql_handle);
  836. Sql_Free(sql_handle);
  837. exit(EXIT_FAILURE);
  838. }
  839. if( !default_codepage.empty() ) {
  840. if( SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage.c_str()) )
  841. Sql_ShowDebug(sql_handle);
  842. }
  843. interServerDb.load();
  844. inter_guild_sql_init();
  845. inter_storage_sql_init();
  846. inter_party_sql_init();
  847. inter_pet_sql_init();
  848. inter_homunculus_sql_init();
  849. inter_mercenary_sql_init();
  850. inter_elemental_sql_init();
  851. inter_mail_sql_init();
  852. inter_auction_sql_init();
  853. inter_clan_init();
  854. geoip_readdb();
  855. return 0;
  856. }
  857. // finalize
  858. void inter_final(void)
  859. {
  860. wis_db.clear();
  861. inter_guild_sql_final();
  862. inter_storage_sql_final();
  863. inter_party_sql_final();
  864. inter_pet_sql_final();
  865. inter_homunculus_sql_final();
  866. inter_mercenary_sql_final();
  867. inter_elemental_sql_final();
  868. inter_mail_sql_final();
  869. inter_auction_sql_final();
  870. inter_clan_final();
  871. if(geoip_cache) aFree(geoip_cache);
  872. return;
  873. }
  874. /**
  875. * IZ 0x388c <len>.W { <storage_table>.? }*?
  876. * Sends storage information to map-server
  877. * @param fd
  878. **/
  879. void inter_Storage_sendInfo(int fd) {
  880. int size = sizeof(struct s_storage_table), len = 4 + interServerDb.size() * size, offset;
  881. // Send storage table information
  882. WFIFOHEAD(fd, len);
  883. WFIFOW(fd, 0) = 0x388c;
  884. WFIFOW(fd, 2) = len;
  885. offset = 4;
  886. for( auto storage : interServerDb ){
  887. memcpy(WFIFOP(fd, offset), storage.second.get(), size);
  888. offset += size;
  889. }
  890. WFIFOSET(fd, len);
  891. }
  892. int inter_mapif_init(int fd)
  893. {
  894. inter_Storage_sendInfo(fd);
  895. return 0;
  896. }
  897. //--------------------------------------------------------
  898. // broadcast sending
  899. int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
  900. {
  901. unsigned char *buf = (unsigned char*)aMalloc((len)*sizeof(unsigned char));
  902. WBUFW(buf,0) = 0x3800;
  903. WBUFW(buf,2) = len;
  904. WBUFL(buf,4) = fontColor;
  905. WBUFW(buf,8) = fontType;
  906. WBUFW(buf,10) = fontSize;
  907. WBUFW(buf,12) = fontAlign;
  908. WBUFW(buf,14) = fontY;
  909. memcpy(WBUFP(buf,16), mes, len - 16);
  910. chmapif_sendallwos(sfd, buf, len);
  911. aFree(buf);
  912. return 0;
  913. }
  914. // Wis sending
  915. int mapif_wis_message( std::shared_ptr<struct WisData> wd ){
  916. unsigned char buf[2048];
  917. int headersize = 12 + 2 * NAME_LENGTH;
  918. if (wd->len > 2047-headersize) wd->len = 2047-headersize; //Force it to fit to avoid crashes. [Skotlex]
  919. WBUFW(buf, 0) = 0x3801;
  920. WBUFW(buf, 2) = headersize+wd->len;
  921. WBUFL(buf, 4) = wd->id;
  922. WBUFL(buf, 8) = wd->gmlvl;
  923. safestrncpy(WBUFCP(buf,12), wd->src, NAME_LENGTH);
  924. safestrncpy(WBUFCP(buf,12 + NAME_LENGTH), wd->dst, NAME_LENGTH);
  925. safestrncpy(WBUFCP(buf,12 + 2*NAME_LENGTH), wd->msg, wd->len);
  926. wd->count = chmapif_sendall(buf,WBUFW(buf,2));
  927. return 0;
  928. }
  929. // Send the requested account_reg
  930. int mapif_account_reg_reply(int fd, uint32 account_id, uint32 char_id, int type)
  931. {
  932. inter_accreg_fromsql(account_id,char_id,fd,type);
  933. return 0;
  934. }
  935. //Request to kick char from a certain map server. [Skotlex]
  936. int mapif_disconnectplayer(int fd, uint32 account_id, uint32 char_id, int reason)
  937. {
  938. if (session_isValid(fd))
  939. {
  940. WFIFOHEAD(fd,7);
  941. WFIFOW(fd,0) = 0x2b1f;
  942. WFIFOL(fd,2) = account_id;
  943. WFIFOB(fd,6) = reason;
  944. WFIFOSET(fd,7);
  945. return 0;
  946. }
  947. return -1;
  948. }
  949. //--------------------------------------------------------
  950. void check_ttl_wisdata(){
  951. t_tick tick = gettick();
  952. for( auto it = wis_db.begin(); it != wis_db.end(); ){
  953. std::shared_ptr<struct WisData> wd = it->second;
  954. if( DIFF_TICK( tick, wd->tick ) > WISDATA_TTL ){
  955. ShowWarning( "inter: wis data id=%d time out : from %s to %s\n", wd->id, wd->src, wd->dst );
  956. it = wis_db.erase( it );
  957. }else{
  958. it++;
  959. }
  960. }
  961. }
  962. //--------------------------------------------------------
  963. // broadcast sending
  964. int mapif_parse_broadcast(int fd)
  965. {
  966. mapif_broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
  967. return 0;
  968. }
  969. /**
  970. * Parse received item broadcast and sends it to all connected map-serves
  971. * ZI 3009 <cmd>.W <len>.W <nameid>.L <source>.W <type>.B <name>.24B <srcname>.24B
  972. * IZ 3809 <cmd>.W <len>.W <nameid>.L <source>.W <type>.B <name>.24B <srcname>.24B
  973. * @param fd
  974. * @return
  975. **/
  976. int mapif_parse_broadcast_item(int fd) {
  977. unsigned char buf[11 + NAME_LENGTH*2];
  978. memcpy(WBUFP(buf, 0), RFIFOP(fd, 0), RFIFOW(fd,2));
  979. WBUFW(buf, 0) = 0x3809;
  980. chmapif_sendallwos(fd, buf, RFIFOW(fd,2));
  981. return 0;
  982. }
  983. // Wis sending result
  984. // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  985. int mapif_wis_reply( int mapserver_fd, char* target, uint8 flag ){
  986. unsigned char buf[27];
  987. WBUFW(buf, 0) = 0x3802;
  988. safestrncpy(WBUFCP(buf, 2), target, NAME_LENGTH);
  989. WBUFB(buf,26) = flag;
  990. return chmapif_send(mapserver_fd, buf, 27);
  991. }
  992. // Wisp/page request to send
  993. int mapif_parse_WisRequest(int fd)
  994. {
  995. char name[NAME_LENGTH];
  996. char esc_name[NAME_LENGTH*2+1];// escaped name
  997. char* data;
  998. size_t len;
  999. int headersize = 8+2*NAME_LENGTH;
  1000. if ( fd <= 0 ) {return 0;} // check if we have a valid fd
  1001. if( RFIFOW( fd, 2 ) - headersize >= WHISPER_MESSAGE_SIZE ){
  1002. ShowWarning("inter: Wis message size too long.\n");
  1003. return 0;
  1004. } else if (RFIFOW(fd,2)-headersize <= 0) { // normaly, impossible, but who knows...
  1005. ShowError("inter: Wis message doesn't exist.\n");
  1006. return 0;
  1007. }
  1008. safestrncpy(name, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex]
  1009. Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH));
  1010. if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", schema_config.char_db, esc_name) )
  1011. Sql_ShowDebug(sql_handle);
  1012. // search if character exists before to ask all map-servers
  1013. if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
  1014. {
  1015. mapif_wis_reply(fd, RFIFOCP(fd, 8), 1);
  1016. }
  1017. else
  1018. {// Character exists. So, ask all map-servers
  1019. // to be sure of the correct name, rewrite it
  1020. Sql_GetData(sql_handle, 0, &data, &len);
  1021. memset(name, 0, NAME_LENGTH);
  1022. memcpy(name, data, zmin(len, NAME_LENGTH));
  1023. // if source is destination, don't ask other servers.
  1024. if( strncmp(RFIFOCP(fd,8), name, NAME_LENGTH) == 0 )
  1025. {
  1026. mapif_wis_reply(fd, RFIFOCP(fd, 8), 1);
  1027. }
  1028. else
  1029. {
  1030. static int wisid = 0;
  1031. // Whether the failure of previous wisp/page transmission (timeout)
  1032. check_ttl_wisdata();
  1033. std::shared_ptr<struct WisData> wd = std::make_shared<struct WisData>();
  1034. wd->id = ++wisid;
  1035. wd->fd = fd;
  1036. wd->len= RFIFOW(fd,2)-headersize;
  1037. wd->gmlvl = RFIFOL(fd,4);
  1038. safestrncpy(wd->src, RFIFOCP(fd,8), NAME_LENGTH);
  1039. safestrncpy(wd->dst, RFIFOCP(fd,8+NAME_LENGTH), NAME_LENGTH);
  1040. safestrncpy(wd->msg, RFIFOCP(fd,8+2*NAME_LENGTH), wd->len);
  1041. wd->tick = gettick();
  1042. wis_db[wd->id] = wd;
  1043. mapif_wis_message( wd );
  1044. }
  1045. }
  1046. Sql_FreeResult(sql_handle);
  1047. return 0;
  1048. }
  1049. // Wisp/page transmission result
  1050. int mapif_parse_WisReply(int fd)
  1051. {
  1052. int32 id;
  1053. uint8 flag;
  1054. id = RFIFOL(fd,2);
  1055. flag = RFIFOB(fd,6);
  1056. std::shared_ptr<struct WisData> wd = util::umap_find( wis_db, id );
  1057. if( wd == nullptr ){
  1058. return 0; // This wisp was probably suppress before, because it was timeout of because of target was found on another map-server
  1059. }
  1060. if ((--wd->count) <= 0 || flag != 1) {
  1061. mapif_wis_reply(wd->fd, wd->src, flag); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target
  1062. wis_db.erase( id );
  1063. }
  1064. return 0;
  1065. }
  1066. // Received wisp message from map-server for ALL gm (just copy the message and resends it to ALL map-servers)
  1067. int mapif_parse_WisToGM(int fd)
  1068. {
  1069. unsigned char buf[2048]; // 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.L <message>.?B
  1070. memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2));
  1071. WBUFW(buf, 0) = 0x3803;
  1072. chmapif_sendall(buf, RFIFOW(fd,2));
  1073. return 0;
  1074. }
  1075. // Save account_reg into sql (type=2)
  1076. int mapif_parse_Registry(int fd)
  1077. {
  1078. uint32 account_id = RFIFOL(fd, 4), char_id = RFIFOL(fd, 8);
  1079. uint16 count = RFIFOW(fd, 12);
  1080. if( count ) {
  1081. int cursor = 14, i;
  1082. bool isLoginActive = session_isActive(login_fd);
  1083. if( isLoginActive )
  1084. chlogif_upd_global_accreg(account_id,char_id);
  1085. for(i = 0; i < count; i++) {
  1086. size_t lenkey = RFIFOB( fd, cursor );
  1087. const char* src_key= RFIFOCP(fd, cursor + 1);
  1088. std::string key( src_key, lenkey );
  1089. cursor += lenkey + 1;
  1090. uint32 index = RFIFOL(fd, cursor);
  1091. cursor += 4;
  1092. switch (RFIFOB(fd, cursor++)) {
  1093. // int
  1094. case 0:
  1095. inter_savereg( account_id, char_id, key.c_str(), index, RFIFOQ( fd, cursor ), nullptr, false );
  1096. cursor += 8;
  1097. break;
  1098. case 1:
  1099. inter_savereg( account_id, char_id, key.c_str(), index, 0, nullptr, false );
  1100. break;
  1101. // str
  1102. case 2:
  1103. {
  1104. size_t len_val = RFIFOB( fd, cursor );
  1105. const char* src_val= RFIFOCP(fd, cursor + 1);
  1106. std::string sval( src_val, len_val );
  1107. cursor += len_val + 1;
  1108. inter_savereg( account_id, char_id, key.c_str(), index, 0, sval.c_str(), true );
  1109. break;
  1110. }
  1111. case 3:
  1112. inter_savereg( account_id, char_id, key.c_str(), index, 0, nullptr, true );
  1113. break;
  1114. default:
  1115. ShowError("mapif_parse_Registry: unknown type %d\n",RFIFOB(fd, cursor - 1));
  1116. return 1;
  1117. }
  1118. }
  1119. if (isLoginActive)
  1120. chlogif_prepsend_global_accreg();
  1121. }
  1122. return 0;
  1123. }
  1124. // Request the value of all registries.
  1125. int mapif_parse_RegistryRequest(int fd)
  1126. {
  1127. //Load Char Registry
  1128. if (RFIFOB(fd,12)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),3);
  1129. //Load Account Registry
  1130. if (RFIFOB(fd,11)) mapif_account_reg_reply(fd,RFIFOL(fd,2),RFIFOL(fd,6),2);
  1131. //Ask Login Server for Account2 values.
  1132. if (RFIFOB(fd,10)) chlogif_request_accreg2(RFIFOL(fd,2),RFIFOL(fd,6));
  1133. return 1;
  1134. }
  1135. void mapif_namechange_ack(int fd, uint32 account_id, uint32 char_id, int type, int flag, char *name)
  1136. {
  1137. WFIFOHEAD(fd, NAME_LENGTH+13);
  1138. WFIFOW(fd, 0) = 0x3806;
  1139. WFIFOL(fd, 2) = account_id;
  1140. WFIFOL(fd, 6) = char_id;
  1141. WFIFOB(fd,10) = type;
  1142. WFIFOB(fd,11) = flag;
  1143. memcpy(WFIFOP(fd, 12), name, NAME_LENGTH);
  1144. WFIFOSET(fd, NAME_LENGTH+13);
  1145. }
  1146. int mapif_parse_NameChangeRequest(int fd)
  1147. {
  1148. uint32 account_id, char_id;
  1149. int type;
  1150. char* name;
  1151. int i;
  1152. account_id = RFIFOL(fd,2);
  1153. char_id = RFIFOL(fd,6);
  1154. type = RFIFOB(fd,10);
  1155. name = RFIFOCP(fd,11);
  1156. // Check Authorised letters/symbols in the name
  1157. if (charserv_config.char_config.char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
  1158. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  1159. if (strchr(charserv_config.char_config.char_name_letters, name[i]) == NULL) {
  1160. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  1161. return 0;
  1162. }
  1163. } else if (charserv_config.char_config.char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
  1164. for (i = 0; i < NAME_LENGTH && name[i]; i++)
  1165. if (strchr(charserv_config.char_config.char_name_letters, name[i]) != NULL) {
  1166. mapif_namechange_ack(fd, account_id, char_id, type, 0, name);
  1167. return 0;
  1168. }
  1169. }
  1170. //TODO: type holds the type of object to rename.
  1171. //If it were a player, it needs to have the guild information and db information
  1172. //updated here, because changing it on the map won't make it be saved [Skotlex]
  1173. //name allowed.
  1174. mapif_namechange_ack(fd, account_id, char_id, type, 1, name);
  1175. return 0;
  1176. }
  1177. //--------------------------------------------------------
  1178. /// Returns the length of the next complete packet to process,
  1179. /// or 0 if no complete packet exists in the queue.
  1180. ///
  1181. /// @param length The minimum allowed length, or -1 for dynamic lookup
  1182. int inter_check_length(int fd, int length)
  1183. {
  1184. if( length == -1 )
  1185. {// variable-length packet
  1186. if( RFIFOREST(fd) < 4 )
  1187. return 0;
  1188. length = RFIFOW(fd,2);
  1189. }
  1190. if( (int)RFIFOREST(fd) < length )
  1191. return 0;
  1192. return length;
  1193. }
  1194. int inter_parse_frommap(int fd)
  1195. {
  1196. int cmd;
  1197. int len = 0;
  1198. cmd = RFIFOW(fd,0);
  1199. // Check is valid packet entry
  1200. if(cmd < 0x3000 || cmd >= 0x3000 + ARRAYLENGTH(inter_recv_packet_length) || inter_recv_packet_length[cmd - 0x3000] == 0)
  1201. return 0;
  1202. // Check packet length
  1203. if((len = inter_check_length(fd, inter_recv_packet_length[cmd - 0x3000])) == 0)
  1204. return 2;
  1205. switch(cmd) {
  1206. case 0x3000: mapif_parse_broadcast(fd); break;
  1207. case 0x3001: mapif_parse_WisRequest(fd); break;
  1208. case 0x3002: mapif_parse_WisReply(fd); break;
  1209. case 0x3003: mapif_parse_WisToGM(fd); break;
  1210. case 0x3004: mapif_parse_Registry(fd); break;
  1211. case 0x3005: mapif_parse_RegistryRequest(fd); break;
  1212. case 0x3006: mapif_parse_NameChangeRequest(fd); break;
  1213. case 0x3007: mapif_parse_accinfo(fd); break;
  1214. /* 0x3008 unused */
  1215. case 0x3009: mapif_parse_broadcast_item(fd); break;
  1216. default:
  1217. if( inter_party_parse_frommap(fd)
  1218. || inter_guild_parse_frommap(fd)
  1219. || inter_storage_parse_frommap(fd)
  1220. || inter_pet_parse_frommap(fd)
  1221. || inter_homunculus_parse_frommap(fd)
  1222. || inter_mercenary_parse_frommap(fd)
  1223. || inter_elemental_parse_frommap(fd)
  1224. || inter_mail_parse_frommap(fd)
  1225. || inter_auction_parse_frommap(fd)
  1226. || inter_quest_parse_frommap(fd)
  1227. || inter_clan_parse_frommap(fd)
  1228. || inter_achievement_parse_frommap(fd)
  1229. )
  1230. break;
  1231. else
  1232. return 0;
  1233. }
  1234. RFIFOSKIP(fd, len);
  1235. return 1;
  1236. }