admin.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. #include "../common/cbasetypes.h"
  2. #include "../common/mmo.h"
  3. #include "../common/core.h"
  4. #include "../common/socket.h"
  5. #include "../common/db.h"
  6. #include "../common/timer.h"
  7. #include "../common/malloc.h"
  8. #include "../common/strlib.h"
  9. #include "../common/showmsg.h"
  10. #include "../common/version.h"
  11. #include "../common/md5calc.h"
  12. #include "../common/lock.h"
  13. #include "login.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <sys/stat.h> // for stat/lstat/fstat
  18. #define MAX_SERVERS 30
  19. extern struct mmo_char_server server[MAX_SERVERS];
  20. extern uint32 auth_num;
  21. extern int account_id_count;
  22. extern char GM_account_filename[1024];
  23. extern char login_log_unknown_packets_filename[1024];
  24. int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len);
  25. int search_account_index(char* account_name);
  26. int mmo_auth_new(struct mmo_account* account, char sex, char* email);
  27. void mmo_auth_sync(void);
  28. int mmo_auth_tostr(char* str, struct auth_data* p);
  29. int read_gm_account(void);
  30. void send_GM_accounts(int fd);
  31. int isGM(int account_id);
  32. //---------------------------------------
  33. // Packet parsing for administation login
  34. //---------------------------------------
  35. int parse_admin(int fd)
  36. {
  37. unsigned int i, j;
  38. char* account_name;
  39. uint32 ipl = session[fd]->client_addr;
  40. char ip[16];
  41. ip2str(ipl, ip);
  42. if( session[fd]->flag.eof )
  43. {
  44. do_close(fd);
  45. ShowInfo("Remote administration has disconnected (session #%d).\n", fd);
  46. return 0;
  47. }
  48. while( RFIFOREST(fd) >= 2 )
  49. {
  50. uint16 command = RFIFOW(fd,0);
  51. switch( command )
  52. {
  53. case 0x7530: // Request of the server version
  54. ShowStatus("'ladmin': Sending of the server version (ip: %s)\n", ip);
  55. WFIFOHEAD(fd,10);
  56. WFIFOW(fd,0) = 0x7531;
  57. WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
  58. WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
  59. WFIFOB(fd,4) = ATHENA_REVISION;
  60. WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
  61. WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
  62. WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
  63. WFIFOW(fd,8) = ATHENA_MOD_VERSION;
  64. WFIFOSET(fd,10);
  65. RFIFOSKIP(fd,2);
  66. break;
  67. case 0x7920: // Request of an accounts list
  68. if (RFIFOREST(fd) < 10)
  69. return 0;
  70. {
  71. int st, ed;
  72. uint16 len;
  73. CREATE_BUFFER(id, int, auth_num);
  74. st = RFIFOL(fd,2);
  75. ed = RFIFOL(fd,6);
  76. RFIFOSKIP(fd,10);
  77. WFIFOW(fd,0) = 0x7921;
  78. if (st < 0)
  79. st = 0;
  80. if (ed > END_ACCOUNT_NUM || ed < st || ed <= 0)
  81. ed = END_ACCOUNT_NUM;
  82. ShowStatus("'ladmin': Sending an accounts list (ask: from %d to %d, ip: %s)\n", st, ed, ip);
  83. // Sort before send
  84. for(i = 0; i < auth_num; i++) {
  85. unsigned int k;
  86. id[i] = i;
  87. for(j = 0; j < i; j++) {
  88. if (auth_dat[id[i]].account_id < auth_dat[id[j]].account_id) {
  89. for(k = i; k > j; k--) {
  90. id[k] = id[k-1];
  91. }
  92. id[j] = i; // id[i]
  93. break;
  94. }
  95. }
  96. }
  97. // Sending accounts information
  98. len = 4;
  99. for(i = 0; i < auth_num && len < 30000; i++) {
  100. int account_id = auth_dat[id[i]].account_id; // use sorted index
  101. if (account_id >= st && account_id <= ed) {
  102. j = id[i];
  103. WFIFOL(fd,len) = account_id;
  104. WFIFOB(fd,len+4) = (unsigned char)isGM(account_id);
  105. memcpy(WFIFOP(fd,len+5), auth_dat[j].userid, 24);
  106. WFIFOB(fd,len+29) = auth_dat[j].sex;
  107. WFIFOL(fd,len+30) = auth_dat[j].logincount;
  108. if (auth_dat[j].state == 0 && auth_dat[j].ban_until_time != 0) // if no state and banished
  109. WFIFOL(fd,len+34) = 7; // 6 = Your are Prohibited to log in until %s
  110. else
  111. WFIFOL(fd,len+34) = auth_dat[j].state;
  112. len += 38;
  113. }
  114. }
  115. WFIFOW(fd,2) = len;
  116. WFIFOSET(fd,len);
  117. //if (id) free(id);
  118. DELETE_BUFFER(id);
  119. }
  120. break;
  121. case 0x7930: // Request for an account creation
  122. if (RFIFOREST(fd) < 91)
  123. return 0;
  124. {
  125. struct mmo_account ma;
  126. memcpy(ma.userid,RFIFOP(fd, 2),NAME_LENGTH);
  127. ma.userid[23] = '\0';
  128. memcpy(ma.passwd, RFIFOP(fd, 26), NAME_LENGTH);
  129. ma.passwd[23] = '\0';
  130. memcpy(ma.lastlogin, "-", 2);
  131. ma.sex = RFIFOB(fd,50);
  132. WFIFOW(fd,0) = 0x7931;
  133. WFIFOL(fd,2) = 0xffffffff;
  134. memcpy(WFIFOP(fd,6), RFIFOP(fd,2), 24);
  135. if (strlen(ma.userid) < 4 || strlen(ma.passwd) < 4) {
  136. ShowNotice("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n", ip);
  137. } else if (ma.sex != 'F' && ma.sex != 'M') {
  138. ShowNotice("'ladmin': Attempt to create an invalid account (account: %s, received pass: %s, invalid sex, ip: %s)\n", ma.userid, ma.passwd, ip);
  139. } else if (account_id_count > END_ACCOUNT_NUM) {
  140. ShowNotice("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, pass: %s, sex: %c, ip: %s)\n", ma.userid, ma.passwd, ma.sex, ip);
  141. } else {
  142. remove_control_chars(ma.userid);
  143. remove_control_chars(ma.passwd);
  144. for(i = 0; i < auth_num; i++) {
  145. if (strncmp(auth_dat[i].userid, ma.userid, 24) == 0) {
  146. ShowNotice("'ladmin': Attempt to create an already existing account (account: %s, pass: %s, received pass: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ma.passwd, ip);
  147. break;
  148. }
  149. }
  150. if (i == auth_num) {
  151. int new_id;
  152. char email[40];
  153. memcpy(email, RFIFOP(fd,51), 40);
  154. email[39] = '\0';
  155. remove_control_chars(email);
  156. new_id = mmo_auth_new(&ma, ma.sex, email);
  157. ShowNotice("'ladmin': Account creation (account: %s (id: %d), pass: %s, sex: %c, email: %s, ip: %s)\n", ma.userid, new_id, ma.passwd, ma.sex, auth_dat[i].email, ip);
  158. WFIFOL(fd,2) = new_id;
  159. mmo_auth_sync();
  160. }
  161. }
  162. WFIFOSET(fd,30);
  163. RFIFOSKIP(fd,91);
  164. }
  165. break;
  166. case 0x7932: // Request for an account deletion
  167. if (RFIFOREST(fd) < 26)
  168. return 0;
  169. WFIFOW(fd,0) = 0x7933;
  170. WFIFOL(fd,2) = 0xFFFFFFFF;
  171. account_name = (char*)RFIFOP(fd,2);
  172. account_name[23] = '\0';
  173. remove_control_chars(account_name);
  174. i = search_account_index(account_name);
  175. if (i != -1) {
  176. // Char-server is notified of deletion (for characters deletion).
  177. unsigned char buf[65535];
  178. WBUFW(buf,0) = 0x2730;
  179. WBUFL(buf,2) = auth_dat[i].account_id;
  180. charif_sendallwos(-1, buf, 6);
  181. // send answer
  182. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  183. WFIFOL(fd,2) = auth_dat[i].account_id;
  184. // save deleted account in log file
  185. ShowNotice("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
  186. mmo_auth_tostr((char*)buf, &auth_dat[i]);
  187. ShowNotice("%s\n", buf);
  188. // delete account
  189. memset(auth_dat[i].userid, '\0', sizeof(auth_dat[i].userid));
  190. auth_dat[i].account_id = -1;
  191. mmo_auth_sync();
  192. } else {
  193. memcpy(WFIFOP(fd,6), account_name, 24);
  194. ShowNotice("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", account_name, ip);
  195. }
  196. WFIFOSET(fd,30);
  197. RFIFOSKIP(fd,26);
  198. break;
  199. case 0x7934: // Request to change a password
  200. if (RFIFOREST(fd) < 50)
  201. return 0;
  202. WFIFOW(fd,0) = 0x7935;
  203. WFIFOL(fd,2) = 0xFFFFFFFF; /// WTF??? an unsigned being set to a -1
  204. account_name = (char*)RFIFOP(fd,2);
  205. account_name[23] = '\0';
  206. remove_control_chars(account_name);
  207. i = search_account_index(account_name);
  208. if (i != -1) {
  209. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  210. memcpy(auth_dat[i].pass, RFIFOP(fd,26), 24);
  211. auth_dat[i].pass[23] = '\0';
  212. remove_control_chars(auth_dat[i].pass);
  213. WFIFOL(fd,2) = auth_dat[i].account_id;
  214. ShowNotice("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ip);
  215. mmo_auth_sync();
  216. } else {
  217. memcpy(WFIFOP(fd,6), account_name, 24);
  218. ShowNotice("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  219. }
  220. WFIFOSET(fd,30);
  221. RFIFOSKIP(fd,50);
  222. break;
  223. case 0x7936: // Request to modify a state
  224. if (RFIFOREST(fd) < 50)
  225. return 0;
  226. {
  227. char error_message[20];
  228. uint32 statut;
  229. WFIFOW(fd,0) = 0x7937;
  230. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  231. account_name = (char*)RFIFOP(fd,2);
  232. account_name[23] = '\0';
  233. remove_control_chars(account_name);
  234. statut = RFIFOL(fd,26);
  235. memcpy(error_message, RFIFOP(fd,30), 20);
  236. error_message[19] = '\0';
  237. remove_control_chars(error_message);
  238. if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s
  239. strcpy(error_message, "-");
  240. }
  241. i = search_account_index(account_name);
  242. if (i != -1) {
  243. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  244. WFIFOL(fd,2) = auth_dat[i].account_id;
  245. if (auth_dat[i].state == statut && strcmp(auth_dat[i].error_message, error_message) == 0)
  246. ShowNotice("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n", account_name, statut, ip);
  247. else {
  248. if (statut == 7)
  249. ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n", auth_dat[i].userid, statut, error_message, ip);
  250. else
  251. ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", auth_dat[i].userid, statut, ip);
  252. if (auth_dat[i].state == 0) {
  253. unsigned char buf[16];
  254. WBUFW(buf,0) = 0x2731;
  255. WBUFL(buf,2) = auth_dat[i].account_id;
  256. WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
  257. WBUFL(buf,7) = statut; // status or final date of a banishment
  258. charif_sendallwos(-1, buf, 11);
  259. /*
  260. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  261. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  262. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
  263. */
  264. }
  265. auth_dat[i].state = statut;
  266. memcpy(auth_dat[i].error_message, error_message, 20);
  267. mmo_auth_sync();
  268. }
  269. } else {
  270. memcpy(WFIFOP(fd,6), account_name, 24);
  271. ShowNotice("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", account_name, statut, ip);
  272. }
  273. WFIFOL(fd,30) = statut;
  274. }
  275. WFIFOSET(fd,34);
  276. RFIFOSKIP(fd,50);
  277. break;
  278. case 0x7938: // Request for servers list and # of online players
  279. {
  280. uint8 server_num = 0;
  281. ShowStatus("'ladmin': Sending of servers list (ip: %s)\n", ip);
  282. for(i = 0; i < MAX_SERVERS; i++) {
  283. if (server[i].fd >= 0) {
  284. WFIFOL(fd,4+server_num*32) = htonl(server[i].ip);
  285. WFIFOW(fd,4+server_num*32+4) = htons(server[i].port);
  286. memcpy(WFIFOP(fd,4+server_num*32+6), server[i].name, 20);
  287. WFIFOW(fd,4+server_num*32+26) = server[i].users;
  288. WFIFOW(fd,4+server_num*32+28) = server[i].maintenance;
  289. WFIFOW(fd,4+server_num*32+30) = server[i].new_;
  290. server_num++;
  291. }
  292. }
  293. WFIFOW(fd,0) = 0x7939;
  294. WFIFOW(fd,2) = 4 + 32 * server_num;
  295. WFIFOSET(fd,4+32*server_num);
  296. RFIFOSKIP(fd,2);
  297. break;
  298. }
  299. case 0x793a: // Request to password check
  300. if (RFIFOREST(fd) < 50)
  301. return 0;
  302. WFIFOW(fd,0) = 0x793b;
  303. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  304. account_name = (char*)RFIFOP(fd,2);
  305. account_name[23] = '\0';
  306. remove_control_chars(account_name);
  307. i = search_account_index(account_name);
  308. if (i != -1) {
  309. char pass[25];
  310. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  311. memcpy(pass, RFIFOP(fd,26), 24);
  312. pass[24] = '\0';
  313. remove_control_chars(pass);
  314. if (strcmp(auth_dat[i].pass, pass) == 0) {
  315. WFIFOL(fd,2) = auth_dat[i].account_id;
  316. ShowNotice("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ip);
  317. } else {
  318. ShowNotice("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", auth_dat[i].userid, pass, ip);
  319. }
  320. } else {
  321. memcpy(WFIFOP(fd,6), account_name, 24);
  322. ShowNotice("'ladmin': Attempt to check the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  323. }
  324. WFIFOSET(fd,30);
  325. RFIFOSKIP(fd,50);
  326. break;
  327. case 0x793c: // Request to modify sex
  328. if (RFIFOREST(fd) < 27)
  329. return 0;
  330. WFIFOW(fd,0) = 0x793d;
  331. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  332. account_name = (char*)RFIFOP(fd,2);
  333. account_name[23] = '\0';
  334. remove_control_chars(account_name);
  335. memcpy(WFIFOP(fd,6), account_name, 24);
  336. {
  337. char sex;
  338. sex = RFIFOB(fd,26);
  339. if (sex != 'F' && sex != 'M') {
  340. if (sex > 31)
  341. ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
  342. else
  343. ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n", account_name, ip);
  344. } else {
  345. i = search_account_index(account_name);
  346. if (i != -1) {
  347. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  348. if (auth_dat[i].sex != ((sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'))) {
  349. unsigned char buf[16];
  350. WFIFOL(fd,2) = auth_dat[i].account_id;
  351. /*
  352. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  353. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  354. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
  355. */
  356. auth_dat[i].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
  357. ShowNotice("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", auth_dat[i].userid, sex, ip);
  358. mmo_auth_sync();
  359. // send to all char-server the change
  360. WBUFW(buf,0) = 0x2723;
  361. WBUFL(buf,2) = auth_dat[i].account_id;
  362. WBUFB(buf,6) = auth_dat[i].sex;
  363. charif_sendallwos(-1, buf, 7);
  364. } else {
  365. ShowNotice("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", auth_dat[i].userid, sex, ip);
  366. }
  367. } else {
  368. ShowNotice("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
  369. }
  370. }
  371. }
  372. WFIFOSET(fd,30);
  373. RFIFOSKIP(fd,27);
  374. break;
  375. case 0x793e: // Request to modify GM level
  376. if (RFIFOREST(fd) < 27)
  377. return 0;
  378. WFIFOW(fd,0) = 0x793f;
  379. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  380. account_name = (char*)RFIFOP(fd,2);
  381. account_name[23] = '\0';
  382. remove_control_chars(account_name);
  383. memcpy(WFIFOP(fd,6), account_name, 24);
  384. {
  385. char new_gm_level;
  386. new_gm_level = RFIFOB(fd,26);
  387. if (new_gm_level < 0 || new_gm_level > 99) {
  388. ShowNotice("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
  389. } else {
  390. i = search_account_index(account_name);
  391. if (i != -1) {
  392. int acc = auth_dat[i].account_id;
  393. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  394. if (isGM(acc) != new_gm_level) {
  395. // modification of the file
  396. FILE *fp, *fp2;
  397. int lock;
  398. char line[512];
  399. int GM_account, GM_level;
  400. int modify_flag;
  401. char tmpstr[24];
  402. time_t raw_time;
  403. if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL) {
  404. if ((fp = fopen(GM_account_filename, "r")) != NULL) {
  405. time(&raw_time);
  406. strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
  407. modify_flag = 0;
  408. // read/write GM file
  409. while(fgets(line, sizeof(line), fp))
  410. {
  411. while(line[0] != '\0' && (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r'))
  412. line[strlen(line)-1] = '\0'; // TODO: remove this
  413. if ((line[0] == '/' && line[1] == '/') || line[0] == '\0')
  414. fprintf(fp2, "%s\n", line);
  415. else {
  416. if (sscanf(line, "%d %d", &GM_account, &GM_level) != 2 && sscanf(line, "%d: %d", &GM_account, &GM_level) != 2)
  417. fprintf(fp2, "%s\n", line);
  418. else if (GM_account != acc)
  419. fprintf(fp2, "%s\n", line);
  420. else if (new_gm_level < 1) {
  421. fprintf(fp2, "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
  422. modify_flag = 1;
  423. } else {
  424. fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
  425. modify_flag = 1;
  426. }
  427. }
  428. }
  429. if (modify_flag == 0)
  430. fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, acc, new_gm_level);
  431. fclose(fp);
  432. } else {
  433. ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
  434. }
  435. if (lock_fclose(fp2, GM_account_filename, &lock) == 0) {
  436. WFIFOL(fd,2) = acc;
  437. ShowNotice("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
  438. // read and send new GM informations
  439. read_gm_account();
  440. send_GM_accounts(-1);
  441. } else {
  442. ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
  443. }
  444. } else {
  445. ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
  446. }
  447. } else {
  448. ShowNotice("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
  449. }
  450. } else {
  451. ShowNotice("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
  452. }
  453. }
  454. }
  455. WFIFOSET(fd,30);
  456. RFIFOSKIP(fd,27);
  457. break;
  458. case 0x7940: // Request to modify e-mail
  459. if (RFIFOREST(fd) < 66)
  460. return 0;
  461. WFIFOW(fd,0) = 0x7941;
  462. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  463. account_name = (char*)RFIFOP(fd,2);
  464. account_name[23] = '\0';
  465. remove_control_chars(account_name);
  466. memcpy(WFIFOP(fd,6), account_name, 24);
  467. {
  468. char email[40];
  469. memcpy(email, RFIFOP(fd,26), 40);
  470. if (e_mail_check(email) == 0) {
  471. ShowNotice("'ladmin': Attempt to give an invalid e-mail (account: %s, ip: %s)\n", account_name, ip);
  472. } else {
  473. remove_control_chars(email);
  474. i = search_account_index(account_name);
  475. if (i != -1) {
  476. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  477. memcpy(auth_dat[i].email, email, 40);
  478. WFIFOL(fd,2) = auth_dat[i].account_id;
  479. ShowNotice("'ladmin': Modification of an email (account: %s, new e-mail: %s, ip: %s)\n", auth_dat[i].userid, email, ip);
  480. mmo_auth_sync();
  481. } else {
  482. ShowNotice("'ladmin': Attempt to modify the e-mail of an unknown account (account: %s, received e-mail: %s, ip: %s)\n", account_name, email, ip);
  483. }
  484. }
  485. }
  486. WFIFOSET(fd,30);
  487. RFIFOSKIP(fd,66);
  488. break;
  489. case 0x7942: // Request to modify memo field
  490. if ((int)RFIFOREST(fd) < 28 || (int)RFIFOREST(fd) < (28 + RFIFOW(fd,26)))
  491. return 0;
  492. WFIFOW(fd,0) = 0x7943;
  493. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  494. account_name = (char*)RFIFOP(fd,2);
  495. account_name[23] = '\0';
  496. remove_control_chars(account_name);
  497. i = search_account_index(account_name);
  498. if (i != -1) {
  499. int size_of_memo = sizeof(auth_dat[i].memo);
  500. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  501. memset(auth_dat[i].memo, '\0', size_of_memo);
  502. if (RFIFOW(fd,26) == 0) {
  503. strncpy(auth_dat[i].memo, "-", size_of_memo);
  504. } else if (RFIFOW(fd,26) > size_of_memo - 1) {
  505. memcpy(auth_dat[i].memo, RFIFOP(fd,28), size_of_memo - 1);
  506. } else {
  507. memcpy(auth_dat[i].memo, RFIFOP(fd,28), RFIFOW(fd,26));
  508. }
  509. auth_dat[i].memo[size_of_memo - 1] = '\0';
  510. remove_control_chars(auth_dat[i].memo);
  511. WFIFOL(fd,2) = auth_dat[i].account_id;
  512. ShowNotice("'ladmin': Modification of a memo field (account: %s, new memo: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].memo, ip);
  513. mmo_auth_sync();
  514. } else {
  515. memcpy(WFIFOP(fd,6), account_name, 24);
  516. ShowNotice("'ladmin': Attempt to modify the memo field of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  517. }
  518. WFIFOSET(fd,30);
  519. RFIFOSKIP(fd,28 + RFIFOW(fd,26));
  520. break;
  521. case 0x7944: // Request to found an account id
  522. if (RFIFOREST(fd) < 26)
  523. return 0;
  524. WFIFOW(fd,0) = 0x7945;
  525. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  526. account_name = (char*)RFIFOP(fd,2);
  527. account_name[23] = '\0';
  528. remove_control_chars(account_name);
  529. i = search_account_index(account_name);
  530. if (i != -1) {
  531. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  532. WFIFOL(fd,2) = auth_dat[i].account_id;
  533. ShowNotice("'ladmin': Request (by the name) of an account id (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
  534. } else {
  535. memcpy(WFIFOP(fd,6), account_name, 24);
  536. ShowNotice("'ladmin': ID request (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  537. }
  538. WFIFOSET(fd,30);
  539. RFIFOSKIP(fd,26);
  540. break;
  541. case 0x7946: // Request to found an account name
  542. if (RFIFOREST(fd) < 6)
  543. return 0;
  544. WFIFOW(fd,0) = 0x7947;
  545. WFIFOL(fd,2) = RFIFOL(fd,2);
  546. memset(WFIFOP(fd,6), '\0', 24);
  547. for(i = 0; i < auth_num; i++) {
  548. if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) {
  549. strncpy((char*)WFIFOP(fd,6), auth_dat[i].userid, 24);
  550. ShowNotice("'ladmin': Request (by id) of an account name (account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, RFIFOL(fd,2), ip);
  551. break;
  552. }
  553. }
  554. if (i == auth_num) {
  555. ShowNotice("'ladmin': Name request (by id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd,2), ip);
  556. strncpy((char*)WFIFOP(fd,6), "", 24);
  557. }
  558. WFIFOSET(fd,30);
  559. RFIFOSKIP(fd,6);
  560. break;
  561. case 0x7948: // Request to change the validity limit (timestamp) (absolute value)
  562. if (RFIFOREST(fd) < 30)
  563. return 0;
  564. {
  565. time_t timestamp;
  566. char tmpstr[2048];
  567. WFIFOW(fd,0) = 0x7949;
  568. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  569. account_name = (char*)RFIFOP(fd,2);
  570. account_name[23] = '\0';
  571. remove_control_chars(account_name);
  572. timestamp = (time_t)RFIFOL(fd,26);
  573. strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
  574. i = search_account_index(account_name);
  575. if (i != -1) {
  576. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  577. ShowNotice("'ladmin': Change of a validity limit (account: %s, new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
  578. auth_dat[i].connect_until_time = timestamp;
  579. WFIFOL(fd,2) = auth_dat[i].account_id;
  580. mmo_auth_sync();
  581. } else {
  582. memcpy(WFIFOP(fd,6), account_name, 24);
  583. ShowNotice("'ladmin': Attempt to change the validity limit of an unknown account (account: %s, received validity: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "unlimited" : tmpstr), ip);
  584. }
  585. WFIFOL(fd,30) = (unsigned int)timestamp;
  586. }
  587. WFIFOSET(fd,34);
  588. RFIFOSKIP(fd,30);
  589. break;
  590. case 0x794a: // Request to change the final date of a banishment (timestamp) (absolute value)
  591. if (RFIFOREST(fd) < 30)
  592. return 0;
  593. {
  594. time_t timestamp;
  595. char tmpstr[2048];
  596. WFIFOW(fd,0) = 0x794b;
  597. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  598. account_name = (char*)RFIFOP(fd,2);
  599. account_name[23] = '\0';
  600. remove_control_chars(account_name);
  601. timestamp = (time_t)RFIFOL(fd,26);
  602. if (timestamp <= time(NULL))
  603. timestamp = 0;
  604. strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
  605. i = search_account_index(account_name);
  606. if (i != -1) {
  607. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  608. WFIFOL(fd,2) = auth_dat[i].account_id;
  609. ShowNotice("'ladmin': Change of the final date of a banishment (account: %s, new final date of banishment: %d (%s), ip: %s)\n", auth_dat[i].userid, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  610. if (auth_dat[i].ban_until_time != timestamp) {
  611. if (timestamp != 0) {
  612. unsigned char buf[16];
  613. WBUFW(buf,0) = 0x2731;
  614. WBUFL(buf,2) = auth_dat[i].account_id;
  615. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  616. WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
  617. charif_sendallwos(-1, buf, 11);
  618. /*
  619. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  620. if (auth_fifo[j].account_id == auth_dat[i].account_id)
  621. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
  622. */
  623. }
  624. auth_dat[i].ban_until_time = timestamp;
  625. mmo_auth_sync();
  626. }
  627. } else {
  628. memcpy(WFIFOP(fd,6), account_name, 24);
  629. ShowNotice("'ladmin': Attempt to change the final date of a banishment of an unknown account (account: %s, received final date of banishment: %d (%s), ip: %s)\n", account_name, timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  630. }
  631. WFIFOL(fd,30) = (unsigned int)timestamp;
  632. }
  633. WFIFOSET(fd,34);
  634. RFIFOSKIP(fd,30);
  635. break;
  636. case 0x794c: // Request to change the final date of a banishment (timestamp) (relative change)
  637. if (RFIFOREST(fd) < 38)
  638. return 0;
  639. {
  640. time_t timestamp;
  641. struct tm *tmtime;
  642. char tmpstr[2048];
  643. WFIFOW(fd,0) = 0x794d;
  644. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  645. account_name = (char*)RFIFOP(fd,2);
  646. account_name[23] = '\0';
  647. remove_control_chars(account_name);
  648. i = search_account_index(account_name);
  649. if (i != -1) {
  650. WFIFOL(fd,2) = auth_dat[i].account_id;
  651. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  652. if (auth_dat[i].ban_until_time == 0 || auth_dat[i].ban_until_time < time(NULL))
  653. timestamp = time(NULL);
  654. else
  655. timestamp = auth_dat[i].ban_until_time;
  656. tmtime = localtime(&timestamp);
  657. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
  658. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
  659. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
  660. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
  661. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
  662. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
  663. timestamp = mktime(tmtime);
  664. if (timestamp != -1) {
  665. if (timestamp <= time(NULL))
  666. timestamp = 0;
  667. strftime(tmpstr, 24, login_config.date_format, localtime(&timestamp));
  668. ShowNotice("'ladmin': Adjustment of a final date of a banishment (account: %s, (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "no banishment" : tmpstr), ip);
  669. if (auth_dat[i].ban_until_time != timestamp) {
  670. if (timestamp != 0) {
  671. unsigned char buf[16];
  672. WBUFW(buf,0) = 0x2731;
  673. WBUFL(buf,2) = auth_dat[i].account_id;
  674. WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
  675. WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment
  676. charif_sendallwos(-1, buf, 11);
  677. /*
  678. for(j = 0; j < AUTH_FIFO_SIZE; j++)
  679. if (auth_fifo[j].account_id == auth_dat[i].account_id) {
  680. auth_fifo[j].login_id1++; // to avoid reconnection error when come back from map-server (char-server will ask again the authentication)
  681. break;
  682. }
  683. */
  684. }
  685. auth_dat[i].ban_until_time = timestamp;
  686. mmo_auth_sync();
  687. }
  688. } else {
  689. strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].ban_until_time));
  690. ShowNotice("'ladmin': Impossible to adjust the final date of a banishment (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].ban_until_time, (auth_dat[i].ban_until_time == 0 ? "no banishment" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
  691. }
  692. WFIFOL(fd,30) = (unsigned long)auth_dat[i].ban_until_time;
  693. } else {
  694. memcpy(WFIFOP(fd,6), account_name, 24);
  695. ShowNotice("'ladmin': Attempt to adjust the final date of a banishment of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  696. WFIFOL(fd,30) = 0;
  697. }
  698. }
  699. WFIFOSET(fd,34);
  700. RFIFOSKIP(fd,38);
  701. break;
  702. case 0x794e: // Request to send a broadcast message
  703. if (RFIFOREST(fd) < 8 || RFIFOREST(fd) < (8 + RFIFOL(fd,4)))
  704. return 0;
  705. WFIFOW(fd,0) = 0x794f;
  706. WFIFOW(fd,2) = 0xFFFF; // WTF???
  707. if (RFIFOL(fd,4) < 1) {
  708. ShowNotice("'ladmin': Receiving a message for broadcast, but message is void (ip: %s)\n", ip);
  709. } else {
  710. // at least 1 char-server
  711. for(i = 0; i < MAX_SERVERS; i++)
  712. if (server[i].fd >= 0)
  713. break;
  714. if (i == MAX_SERVERS) {
  715. ShowNotice("'ladmin': Receiving a message for broadcast, but no char-server is online (ip: %s)\n", ip);
  716. } else {
  717. unsigned char buf[32000];
  718. char message[32000];
  719. WFIFOW(fd,2) = 0;
  720. memset(message, '\0', sizeof(message));
  721. memcpy(message, RFIFOP(fd,8), RFIFOL(fd,4));
  722. message[sizeof(message)-1] = '\0';
  723. remove_control_chars(message);
  724. if (RFIFOW(fd,2) == 0)
  725. ShowNotice("'ladmin': Receiving a message for broadcast (message (in yellow): %s, ip: %s)\n", message, ip);
  726. else
  727. ShowNotice("'ladmin': Receiving a message for broadcast (message (in blue): %s, ip: %s)\n", message, ip);
  728. // send same message to all char-servers (no answer)
  729. memcpy(WBUFP(buf,0), RFIFOP(fd,0), 8 + RFIFOL(fd,4));
  730. WBUFW(buf,0) = 0x2726;
  731. charif_sendallwos(-1, buf, 8 + RFIFOL(fd,4));
  732. }
  733. }
  734. WFIFOSET(fd,4);
  735. RFIFOSKIP(fd,8 + RFIFOL(fd,4));
  736. break;
  737. case 0x7950: // Request to change the validity limite (timestamp) (relative change)
  738. if (RFIFOREST(fd) < 38)
  739. return 0;
  740. {
  741. time_t timestamp;
  742. struct tm *tmtime;
  743. char tmpstr[2048];
  744. char tmpstr2[2048];
  745. WFIFOW(fd,0) = 0x7951;
  746. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  747. account_name = (char*)RFIFOP(fd,2);
  748. account_name[23] = '\0';
  749. remove_control_chars(account_name);
  750. i = search_account_index(account_name);
  751. if (i != -1) {
  752. WFIFOL(fd,2) = auth_dat[i].account_id;
  753. memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
  754. timestamp = auth_dat[i].connect_until_time;
  755. if (timestamp == 0 || timestamp < time(NULL))
  756. timestamp = time(NULL);
  757. tmtime = localtime(&timestamp);
  758. tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
  759. tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
  760. tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
  761. tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
  762. tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
  763. tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
  764. timestamp = mktime(tmtime);
  765. if (timestamp != -1) {
  766. strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].connect_until_time));
  767. strftime(tmpstr2, 24, login_config.date_format, localtime(&timestamp));
  768. ShowNotice("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
  769. auth_dat[i].connect_until_time = timestamp;
  770. mmo_auth_sync();
  771. WFIFOL(fd,30) = (unsigned long)auth_dat[i].connect_until_time;
  772. } else {
  773. strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].connect_until_time));
  774. ShowNotice("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].connect_until_time, (auth_dat[i].connect_until_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
  775. WFIFOL(fd,30) = 0;
  776. }
  777. } else {
  778. memcpy(WFIFOP(fd,6), account_name, 24);
  779. ShowNotice("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  780. WFIFOL(fd,30) = 0;
  781. }
  782. }
  783. WFIFOSET(fd,34);
  784. RFIFOSKIP(fd,38);
  785. break;
  786. case 0x7952: // Request about informations of an account (by account name)
  787. if (RFIFOREST(fd) < 26)
  788. return 0;
  789. WFIFOW(fd,0) = 0x7953;
  790. WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
  791. account_name = (char*)RFIFOP(fd,2);
  792. account_name[23] = '\0';
  793. remove_control_chars(account_name);
  794. i = search_account_index(account_name);
  795. if (i != -1) {
  796. WFIFOL(fd,2) = auth_dat[i].account_id;
  797. WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
  798. memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
  799. WFIFOB(fd,31) = auth_dat[i].sex;
  800. WFIFOL(fd,32) = auth_dat[i].logincount;
  801. WFIFOL(fd,36) = auth_dat[i].state;
  802. memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
  803. memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
  804. memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
  805. memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
  806. WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time;
  807. WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time;
  808. WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo);
  809. if (auth_dat[i].memo[0]) {
  810. memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
  811. }
  812. ShowNotice("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
  813. WFIFOSET(fd,150+strlen(auth_dat[i].memo));
  814. } else {
  815. memcpy(WFIFOP(fd,7), account_name, 24);
  816. WFIFOW(fd,148) = 0;
  817. ShowNotice("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
  818. WFIFOSET(fd,150);
  819. }
  820. RFIFOSKIP(fd,26);
  821. break;
  822. case 0x7954: // Request about information of an account (by account id)
  823. if (RFIFOREST(fd) < 6)
  824. return 0;
  825. WFIFOW(fd,0) = 0x7953;
  826. WFIFOL(fd,2) = RFIFOL(fd,2);
  827. memset(WFIFOP(fd,7), '\0', 24);
  828. for(i = 0; i < auth_num; i++) {
  829. if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) {
  830. ShowNotice("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, RFIFOL(fd,2), ip);
  831. WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
  832. memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
  833. WFIFOB(fd,31) = auth_dat[i].sex;
  834. WFIFOL(fd,32) = auth_dat[i].logincount;
  835. WFIFOL(fd,36) = auth_dat[i].state;
  836. memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
  837. memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
  838. memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
  839. memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
  840. WFIFOL(fd,140) = (unsigned long)auth_dat[i].connect_until_time;
  841. WFIFOL(fd,144) = (unsigned long)auth_dat[i].ban_until_time;
  842. WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo);
  843. if (auth_dat[i].memo[0]) {
  844. memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
  845. }
  846. WFIFOSET(fd,150+strlen(auth_dat[i].memo));
  847. break;
  848. }
  849. }
  850. if (i == auth_num) {
  851. ShowNotice("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd,2), ip);
  852. strncpy((char*)WFIFOP(fd,7), "", 24);
  853. WFIFOW(fd,148) = 0;
  854. WFIFOSET(fd,150);
  855. }
  856. RFIFOSKIP(fd,6);
  857. break;
  858. case 0x7955: // Request to reload GM file (no answer)
  859. ShowStatus("'ladmin': Request to re-load GM configuration file (ip: %s).\n", ip);
  860. read_gm_account();
  861. // send GM accounts to all char-servers
  862. send_GM_accounts(-1);
  863. RFIFOSKIP(fd,2);
  864. break;
  865. default:
  866. {
  867. FILE *logfp;
  868. char tmpstr[24];
  869. time_t raw_time;
  870. logfp = fopen(login_log_unknown_packets_filename, "a");
  871. if (logfp) {
  872. time(&raw_time);
  873. strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
  874. fprintf(logfp, "%s: receiving of an unknown packet -> disconnection\n", tmpstr);
  875. fprintf(logfp, "parse_admin: connection #%d (ip: %s), packet: 0x%x (with being read: %lu).\n", fd, ip, command, (unsigned long)RFIFOREST(fd));
  876. fprintf(logfp, "Detail (in hex):\n");
  877. fprintf(logfp, "---- 00-01-02-03-04-05-06-07 08-09-0A-0B-0C-0D-0E-0F\n");
  878. memset(tmpstr, '\0', sizeof(tmpstr));
  879. for(i = 0; i < RFIFOREST(fd); i++) {
  880. if ((i & 15) == 0)
  881. fprintf(logfp, "%04X ",i);
  882. fprintf(logfp, "%02x ", RFIFOB(fd,i));
  883. if (RFIFOB(fd,i) > 0x1f)
  884. tmpstr[i % 16] = RFIFOB(fd,i);
  885. else
  886. tmpstr[i % 16] = '.';
  887. if ((i - 7) % 16 == 0) // -8 + 1
  888. fprintf(logfp, " ");
  889. else if ((i + 1) % 16 == 0) {
  890. fprintf(logfp, " %s\n", tmpstr);
  891. memset(tmpstr, '\0', sizeof(tmpstr));
  892. }
  893. }
  894. if (i % 16 != 0) {
  895. for(j = i; j % 16 != 0; j++) {
  896. fprintf(logfp, " ");
  897. if ((j - 7) % 16 == 0) // -8 + 1
  898. fprintf(logfp, " ");
  899. }
  900. fprintf(logfp, " %s\n", tmpstr);
  901. }
  902. fprintf(logfp, "\n");
  903. fclose(logfp);
  904. }
  905. }
  906. ShowStatus("'ladmin': End of connection, unknown packet (ip: %s)\n", ip);
  907. set_eof(fd);
  908. return 0;
  909. }
  910. }
  911. RFIFOSKIP(fd,RFIFOREST(fd));
  912. return 0;
  913. }