inter.cpp 45 KB

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