ladmin.c 113 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. ///////////////////////////////////////////////////////////////////////////
  4. // EAthena login-server remote administration tool
  5. ///////////////////////////////////////////////////////////////////////////
  6. #include "../common/cbasetypes.h"
  7. #include "../common/core.h"
  8. #include "../common/strlib.h"
  9. #include "../common/socket.h"
  10. #include "../common/timer.h"
  11. #include "../common/version.h"
  12. #include "../common/mmo.h"
  13. #include "../common/md5calc.h"
  14. #include "../common/showmsg.h"
  15. #include "ladmin.h"
  16. #include <sys/types.h>
  17. #include <time.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <signal.h>
  21. #include <fcntl.h>
  22. #include <string.h> // str*
  23. #include <stdarg.h> // valist
  24. //-------------------------------INSTRUCTIONS------------------------------
  25. // Set the variables below:
  26. // IP of the login server.
  27. // Port where the login-server listens incoming packets.
  28. // Password of administration (same of config_athena.conf).
  29. // IMPORTANT:
  30. // Be sure that you authorize remote administration in login-server
  31. // (see login_athena.conf, 'admin_state' parameter)
  32. //-------------------------------------------------------------------------
  33. char loginserverip[16] = "127.0.0.1"; // IP of login-server
  34. int loginserverport = 6900; // Port of login-server
  35. char loginserveradminpassword[24] = "admin"; // Administration password
  36. int passenc = 0; // Encoding type of the password
  37. char ladmin_log_filename[1024] = "log/ladmin.log";
  38. char date_format[32] = "%Y-%m-%d %H:%M:%S";
  39. //-------------------------------------------------------------------------
  40. // LIST of COMMANDs that you can type at the prompt:
  41. // To use these commands you can only type only the first letters.
  42. // You must type a minimum of letters (you can not type 'a',
  43. // because ladmin doesn't know if it's for 'aide' or for 'add')
  44. // <Example> q <= quit, li <= list, pass <= passwd, etc.
  45. //
  46. // Note: every time you must give a account_name, you can use "" or '' (spaces can be included)
  47. //
  48. // aide/help/?
  49. // Display the description of the commands
  50. // aide/help/? [command]
  51. // Display the description of the specified command
  52. //
  53. // add <account_name> <sex> <password>
  54. // Create an account with the default email (a@a.com).
  55. // Concerning the sex, only the first letter is used (F or M).
  56. // The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.
  57. // When the password is omitted, the input is done without displaying of the pressed keys.
  58. // <example> add testname Male testpass
  59. //
  60. // ban/banish yyyy/mm/dd hh:mm:ss <account name>
  61. // Changes the final date of a banishment of an account.
  62. // Like banset, but <account name> is at end.
  63. //
  64. // banadd <account_name> <modifier>
  65. // Adds or substracts time from the final date of a banishment of an account.
  66. // Modifier is done as follows:
  67. // Adjustment value (-1, 1, +1, etc...)
  68. // Modified element:
  69. // a or y: year
  70. // m: month
  71. // j or d: day
  72. // h: hour
  73. // mn: minute
  74. // s: second
  75. // <example> banadd testname +1m-2mn1s-6y
  76. // this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
  77. // NOTE: If you modify the final date of a non-banished account,
  78. // you fix the final date to (actual time +- adjustments)
  79. //
  80. // banset <account_name> yyyy/mm/dd [hh:mm:ss]
  81. // Changes the final date of a banishment of an account.
  82. // Default time [hh:mm:ss]: 23:59:59.
  83. // banset <account_name> 0
  84. // Set a non-banished account (0 = unbanished).
  85. //
  86. // block <account name>
  87. // Set state 5 (You have been blocked by the GM Team) to an account.
  88. // Like state <account name> 5.
  89. //
  90. // check <account_name> <password>
  91. // Check the validity of a password for an account
  92. // NOTE: Server will never send back a password.
  93. // It's the only method you have to know if a password is correct.
  94. // The other method is to have a ('physical') access to the accounts file.
  95. //
  96. // create <account_name> <sex> <email> <password>
  97. // Like the 'add' command, but with e-mail moreover.
  98. // <example> create testname Male my@mail.com testpass
  99. //
  100. // del <account name>
  101. // Remove an account.
  102. // This order requires confirmation. After confirmation, the account is deleted.
  103. //
  104. // email <account_name> <email>
  105. // Modify the e-mail of an account.
  106. //
  107. // getcount
  108. // Give the number of players online on all char-servers.
  109. //
  110. // gm <account_name> [GM_level]
  111. // Modify the GM level of an account.
  112. // Default value remove GM level (GM level = 0).
  113. // <example> gm testname 80
  114. //
  115. // id <account name>
  116. // Give the id of an account.
  117. //
  118. // info <account_id>
  119. // Display complete information of an account.
  120. //
  121. // kami <message>
  122. // Sends a broadcast message on all map-server (in yellow).
  123. // kamib <message>
  124. // Sends a broadcast message on all map-server (in blue).
  125. //
  126. // list/ls [start_id [end_id]]
  127. // Display a list of accounts.
  128. // 'start_id', 'end_id': indicate end and start identifiers.
  129. // Research by name is not possible with this command.
  130. // <example> list 10 9999999
  131. //
  132. // listBan/lsBan [start_id [end_id]]
  133. // Like list/ls, but only for accounts with state or banished
  134. //
  135. // listGM/lsGM [start_id [end_id]]
  136. // Like list/ls, but only for GM accounts
  137. //
  138. // listOK/lsOK [start_id [end_id]]
  139. // Like list/ls, but only for accounts without state and not banished
  140. //
  141. // memo <account_name> <memo>
  142. // Modify the memo of an account.
  143. // 'memo': it can have until 253 characters (with spaces or not).
  144. //
  145. // name <account_id>
  146. // Give the name of an account.
  147. //
  148. // passwd <account_name> <new_password>
  149. // Change the password of an account.
  150. // When new password is omitted, the input is done without displaying of the pressed keys.
  151. //
  152. // quit/end/exit
  153. // End of the program of administration
  154. //
  155. // reloadGM
  156. // Reload GM configuration file
  157. //
  158. // search <expression>
  159. // Seek accounts.
  160. // Displays the accounts whose names correspond.
  161. // search -r/-e/--expr/--regex <expression>
  162. // Seek accounts by regular expression.
  163. // Displays the accounts whose names correspond.
  164. //
  165. // sex <account_name> <sex>
  166. // Modify the sex of an account.
  167. // <example> sex testname Male
  168. //
  169. // state <account_name> <new_state> <error_message_#7>
  170. // Change the state of an account.
  171. // 'new_state': state is the state of the packet 0x006a + 1. The possibilities are:
  172. // 0 = Account ok 6 = Your Game's EXE file is not the latest version
  173. // 1 = Unregistered ID 7 = You are Prohibited to log in until %s
  174. // 2 = Incorrect Password 8 = Server is jammed due to over populated
  175. // 3 = This ID is expired 9 = No MSG
  176. // 4 = Rejected from Server 100 = This ID has been totally erased
  177. // 5 = You have been blocked by the GM Team
  178. // all other values are 'No MSG', then use state 9 please.
  179. // 'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
  180. //
  181. // timeadd <account_name> <modifier>
  182. // Adds or substracts time from the validity limit of an account.
  183. // Modifier is done as follows:
  184. // Adjustment value (-1, 1, +1, etc...)
  185. // Modified element:
  186. // a or y: year
  187. // m: month
  188. // j or d: day
  189. // h: hour
  190. // mn: minute
  191. // s: second
  192. // <example> timeadd testname +1m-2mn1s-6y
  193. // this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
  194. // NOTE: You can not modify a unlimited validity limit.
  195. // If you want modify it, you want probably create a limited validity limit.
  196. // So, at first, you must set the validity limit to a date/time.
  197. //
  198. // timeset <account_name> yyyy/mm/dd [hh:mm:ss]
  199. // Changes the validity limit of an account.
  200. // Default time [hh:mm:ss]: 23:59:59.
  201. // timeset <account_name> 0
  202. // Gives an unlimited validity limit (0 = unlimited).
  203. //
  204. // unban/unbanish <account name>
  205. // Unban an account.
  206. // Like banset <account name> 0.
  207. //
  208. // unblock <account name>
  209. // Set state 0 (Account ok) to an account.
  210. // Like state <account name> 0.
  211. //
  212. // version
  213. // Display the version of the login-server.
  214. //
  215. // who <account name>
  216. // Displays complete information of an account.
  217. //
  218. //-------------------------------------------------------------------------
  219. int login_fd;
  220. int login_ip;
  221. int bytes_to_read = 0; // flag to know if we waiting bytes from login-server
  222. char command[1024];
  223. char parameters[1024];
  224. int list_first, list_last, list_type, list_count; // parameter to display a list of accounts
  225. int already_exit_function = 0; // sometimes, the exit function is called twice... so, don't log twice the message
  226. //------------------------------
  227. // Writing function of logs file
  228. //------------------------------
  229. int ladmin_log(char *fmt, ...)
  230. {
  231. FILE *logfp;
  232. va_list ap;
  233. time_t t;
  234. char tmpstr[2048];
  235. va_start(ap, fmt);
  236. logfp = fopen(ladmin_log_filename, "a");
  237. if (logfp) {
  238. if (fmt[0] == '\0') // jump a line if no message
  239. fprintf(logfp, "\n");
  240. else {
  241. t = time(NULL);
  242. strftime(tmpstr, 24, date_format, localtime(&t));
  243. sprintf(tmpstr + strlen(tmpstr), ": %s", fmt);
  244. vfprintf(logfp, tmpstr, ap);
  245. }
  246. fclose(logfp);
  247. }
  248. va_end(ap);
  249. return 0;
  250. }
  251. //---------------------------------------------
  252. // Function to return ordonal text of a number.
  253. //---------------------------------------------
  254. char* makeordinal(int number)
  255. {
  256. if ((number % 10) < 4 && (number % 10) != 0 && (number < 10 || number > 20)) {
  257. if ((number % 10) == 1)
  258. return "st";
  259. else if ((number % 10) == 2)
  260. return "nd";
  261. else
  262. return "rd";
  263. } else {
  264. return "th";
  265. }
  266. return "";
  267. }
  268. //-----------------------------------------------------------------------------------------
  269. // Function to test of the validity of an account name (return 0 if incorrect, and 1 if ok)
  270. //-----------------------------------------------------------------------------------------
  271. int verify_accountname(char* account_name)
  272. {
  273. int i;
  274. for(i = 0; account_name[i]; i++) {
  275. if (account_name[i] < 32) {
  276. ShowMessage("Illegal character found in the account name (%d%s character).\n", i+1, makeordinal(i+1));
  277. ladmin_log("Illegal character found in the account name (%d%s character).\n", i+1, makeordinal(i+1));
  278. return 0;
  279. }
  280. }
  281. if (strlen(account_name) < 4) {
  282. ShowMessage("Account name is too short. Please input an account name of 4-23 bytes.\n");
  283. ladmin_log("Account name is too short. Please input an account name of 4-23 bytes.\n");
  284. return 0;
  285. }
  286. if (strlen(account_name) > 23) {
  287. ShowMessage("Account name is too long. Please input an account name of 4-23 bytes.\n");
  288. ladmin_log("Account name is too long. Please input an account name of 4-23 bytes.\n");
  289. return 0;
  290. }
  291. return 1;
  292. }
  293. //----------------------------------
  294. // Sub-function: Input of a password
  295. //----------------------------------
  296. int typepasswd(char * password)
  297. {
  298. char password1[1023], password2[1023];
  299. int letter;
  300. int i;
  301. ladmin_log("No password was given. Request to obtain a password.\n");
  302. memset(password1, '\0', sizeof(password1));
  303. memset(password2, '\0', sizeof(password2));
  304. ShowMessage("\033[1;36m Type the password > \033[0;32;42m");
  305. i = 0;
  306. while ((letter = getchar()) != '\n')
  307. password1[i++] = letter;
  308. ShowMessage("\033[0m\033[1;36m Verify the password > \033[0;32;42m");
  309. i = 0;
  310. while ((letter = getchar()) != '\n')
  311. password2[i++] = letter;
  312. ShowMessage("\033[0m");
  313. fflush(stdout);
  314. fflush(stdin);
  315. if (strcmp(password1, password2) != 0) {
  316. ShowMessage("Password verification failed. Please input same password.\n");
  317. ladmin_log("Password verification failed. Please input same password.\n");
  318. ladmin_log(" First password: %s, second password: %s.\n", password1, password2);
  319. return 0;
  320. }
  321. ladmin_log("Typed password: %s.\n", password1);
  322. strcpy(password, password1);
  323. return 1;
  324. }
  325. //------------------------------------------------------------------------------------
  326. // Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
  327. //------------------------------------------------------------------------------------
  328. int verify_password(char * password)
  329. {
  330. int i;
  331. for(i = 0; password[i]; i++) {
  332. if (password[i] < 32) {
  333. ShowMessage("Illegal character found in the password (%d%s character).\n", i+1, makeordinal(i+1));
  334. ladmin_log("Illegal character found in the password (%d%s character).\n", i+1, makeordinal(i+1));
  335. return 0;
  336. }
  337. }
  338. if (strlen(password) < 4) {
  339. ShowMessage("Account name is too short. Please input an account name of 4-23 bytes.\n");
  340. ladmin_log("Account name is too short. Please input an account name of 4-23 bytes.\n");
  341. return 0;
  342. }
  343. if (strlen(password) > 23) {
  344. ShowMessage("Password is too long. Please input a password of 4-23 bytes.\n");
  345. ladmin_log("Password is too long. Please input a password of 4-23 bytes.\n");
  346. return 0;
  347. }
  348. return 1;
  349. }
  350. //------------------------------------------------------------------
  351. // Sub-function: Check the name of a command (return complete name)
  352. //-----------------------------------------------------------------
  353. int check_command(char * command)
  354. {
  355. // help
  356. if (strncmp(command, "help", 1) == 0 && strncmp(command, "help", strlen(command)) == 0)
  357. strcpy(command, "help");
  358. // general commands
  359. else if (strncmp(command, "add", 2) == 0 && strncmp(command, "add", strlen(command)) == 0) // not 1 letter command: 'aide' or 'add'?
  360. strcpy(command, "add");
  361. else if ((strncmp(command, "ban", 3) == 0 && strncmp(command, "ban", strlen(command)) == 0) ||
  362. (strncmp(command, "banish", 4) == 0 && strncmp(command, "banish", strlen(command)) == 0))
  363. strcpy(command, "ban");
  364. else if ((strncmp(command, "banadd", 4) == 0 && strncmp(command, "banadd", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
  365. strcmp(command, "ba") == 0)
  366. strcpy(command, "banadd");
  367. else if ((strncmp(command, "banset", 4) == 0 && strncmp(command, "banset", strlen(command)) == 0) || // not 1 letter command: 'ba' or 'bs'? 'banadd' or 'banset' ?
  368. strcmp(command, "bs") == 0)
  369. strcpy(command, "banset");
  370. else if (strncmp(command, "block", 2) == 0 && strncmp(command, "block", strlen(command)) == 0)
  371. strcpy(command, "block");
  372. else if (strncmp(command, "check", 2) == 0 && strncmp(command, "check", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
  373. strcpy(command, "check");
  374. else if (strncmp(command, "create", 2) == 0 && strncmp(command, "create", strlen(command)) == 0) // not 1 letter command: 'check' or 'create'?
  375. strcpy(command, "create");
  376. else if (strncmp(command, "delete", 1) == 0 && strncmp(command, "delete", strlen(command)) == 0)
  377. strcpy(command, "delete");
  378. else if ((strncmp(command, "email", 2) == 0 && strncmp(command, "email", strlen(command)) == 0) || // not 1 letter command: 'email', 'end' or 'exit'?
  379. (strncmp(command, "e-mail", 2) == 0 && strncmp(command, "e-mail", strlen(command)) == 0))
  380. strcpy(command, "email");
  381. else if (strncmp(command, "getcount", 2) == 0 && strncmp(command, "getcount", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
  382. strcpy(command, "getcount");
  383. // else if (strncmp(command, "gm", 2) == 0 && strncmp(command, "gm", strlen(command)) == 0) // not 1 letter command: 'getcount' or 'gm'?
  384. // strcpy(command, "gm");
  385. // else if (strncmp(command, "id", 2) == 0 && strncmp(command, "id", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
  386. // strcpy(command, "id");
  387. else if (strncmp(command, "info", 2) == 0 && strncmp(command, "info", strlen(command)) == 0) // not 1 letter command: 'id' or 'info'?
  388. strcpy(command, "info");
  389. // else if (strncmp(command, "kami", 4) == 0 && strncmp(command, "kami", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
  390. // strcpy(command, "kami");
  391. // else if (strncmp(command, "kamib", 5) == 0 && strncmp(command, "kamib", strlen(command)) == 0) // only all letters command: 'kami' or 'kamib'?
  392. // strcpy(command, "kamib");
  393. else if ((strncmp(command, "list", 2) == 0 && strncmp(command, "list", strlen(command)) == 0) || // 'list' is default list command // not 1 letter command: 'list'?
  394. strcmp(command, "ls") == 0)
  395. strcpy(command, "list");
  396. else if ((strncmp(command, "listban", 5) == 0 && strncmp(command, "listban", strlen(command)) == 0) ||
  397. (strncmp(command, "lsban", 3) == 0 && strncmp(command, "lsban", strlen(command)) == 0) ||
  398. strcmp(command, "lb") == 0)
  399. strcpy(command, "listban");
  400. else if ((strncmp(command, "listgm", 5) == 0 && strncmp(command, "listgm", strlen(command)) == 0) ||
  401. (strncmp(command, "lsgm", 3) == 0 && strncmp(command, "lsgm", strlen(command)) == 0) ||
  402. strcmp(command, "lg") == 0)
  403. strcpy(command, "listgm");
  404. else if ((strncmp(command, "listok", 5) == 0 && strncmp(command, "listok", strlen(command)) == 0) ||
  405. (strncmp(command, "lsok", 3) == 0 && strncmp(command, "lsok", strlen(command)) == 0) ||
  406. strcmp(command, "lo") == 0)
  407. strcpy(command, "listok");
  408. else if (strncmp(command, "memo", 1) == 0 && strncmp(command, "memo", strlen(command)) == 0)
  409. strcpy(command, "memo");
  410. else if (strncmp(command, "name", 1) == 0 && strncmp(command, "name", strlen(command)) == 0)
  411. strcpy(command, "name");
  412. else if ((strncmp(command, "password", 1) == 0 && strncmp(command, "password", strlen(command)) == 0) ||
  413. strcmp(command, "passwd") == 0)
  414. strcpy(command, "password");
  415. else if (strncmp(command, "reloadgm", 1) == 0 && strncmp(command, "reloadgm", strlen(command)) == 0)
  416. strcpy(command, "reloadgm");
  417. else if (strncmp(command, "search", 3) == 0 && strncmp(command, "search", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
  418. strcpy(command, "search"); // not 2 letters command: 'search' or 'sex'?
  419. // else if (strncmp(command, "sex", 3) == 0 && strncmp(command, "sex", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
  420. // strcpy(command, "sex"); // not 2 letters command: 'search' or 'sex'?
  421. else if (strncmp(command, "state", 2) == 0 && strncmp(command, "state", strlen(command)) == 0) // not 1 letter command: 'search', 'state' or 'sex'?
  422. strcpy(command, "state");
  423. else if ((strncmp(command, "timeadd", 5) == 0 && strncmp(command, "timeadd", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
  424. strcmp(command, "ta") == 0)
  425. strcpy(command, "timeadd");
  426. else if ((strncmp(command, "timeset", 5) == 0 && strncmp(command, "timeset", strlen(command)) == 0) || // not 1 letter command: 'ta' or 'ts'? 'timeadd' or 'timeset'?
  427. strcmp(command, "ts") == 0)
  428. strcpy(command, "timeset");
  429. else if ((strncmp(command, "unban", 5) == 0 && strncmp(command, "unban", strlen(command)) == 0) ||
  430. (strncmp(command, "unbanish", 4) == 0 && strncmp(command, "unbanish", strlen(command)) == 0))
  431. strcpy(command, "unban");
  432. else if (strncmp(command, "unblock", 4) == 0 && strncmp(command, "unblock", strlen(command)) == 0)
  433. strcpy(command, "unblock");
  434. else if (strncmp(command, "version", 1) == 0 && strncmp(command, "version", strlen(command)) == 0)
  435. strcpy(command, "version");
  436. else if (strncmp(command, "who", 1) == 0 && strncmp(command, "who", strlen(command)) == 0)
  437. strcpy(command, "who");
  438. // quit
  439. else if (strncmp(command, "quit", 1) == 0 && strncmp(command, "quit", strlen(command)) == 0)
  440. strcpy(command, "quit");
  441. else if (strncmp(command, "exit", 2) == 0 && strncmp(command, "exit", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
  442. strcpy(command, "exit");
  443. else if (strncmp(command, "end", 2) == 0 && strncmp(command, "end", strlen(command)) == 0) // not 1 letter command: 'email', 'end' or 'exit'?
  444. strcpy(command, "end");
  445. return 0;
  446. }
  447. //-----------------------------------------
  448. // Sub-function: Display commands of ladmin
  449. //-----------------------------------------
  450. void display_help(char* param)
  451. {
  452. char command[1023];
  453. int i;
  454. memset(command, '\0', sizeof(command));
  455. if (sscanf(param, "%s ", command) < 1 || strlen(command) == 0)
  456. strcpy(command, ""); // any value that is not a command
  457. if (command[0] == '?')
  458. strcpy(command, "help");
  459. // lowercase for command
  460. for (i = 0; command[i]; i++)
  461. command[i] = TOLOWER(command[i]);
  462. // Analyse of the command
  463. check_command(command); // give complete name to the command
  464. ladmin_log("Displaying of the commands or a command.\n");
  465. if (strcmp(command, "help") == 0 ) {
  466. ShowMessage("aide/help/?\n");
  467. ShowMessage(" Display the description of the commands\n");
  468. ShowMessage("aide/help/? [command]\n");
  469. ShowMessage(" Display the description of the specified command\n");
  470. // general commands
  471. } else if (strcmp(command, "add") == 0) {
  472. ShowMessage("add <account_name> <sex> <password>\n");
  473. ShowMessage(" Create an account with the default email (a@a.com).\n");
  474. ShowMessage(" Concerning the sex, only the first letter is used (F or M).\n");
  475. ShowMessage(" The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.\n");
  476. ShowMessage(" When the password is omitted,\n");
  477. ShowMessage(" the input is done without displaying of the pressed keys.\n");
  478. ShowMessage(" <example> add testname Male testpass\n");
  479. } else if (strcmp(command, "ban") == 0) {
  480. ShowMessage("ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
  481. ShowMessage(" Changes the final date of a banishment of an account.\n");
  482. ShowMessage(" Like banset, but <account name> is at end.\n");
  483. } else if (strcmp(command, "banadd") == 0) {
  484. ShowMessage("banadd <account_name> <modifier>\n");
  485. ShowMessage(" Adds or substracts time from the final date of a banishment of an account.\n");
  486. ShowMessage(" Modifier is done as follows:\n");
  487. ShowMessage(" Adjustment value (-1, 1, +1, etc...)\n");
  488. ShowMessage(" Modified element:\n");
  489. ShowMessage(" a or y: year\n");
  490. ShowMessage(" m: month\n");
  491. ShowMessage(" j or d: day\n");
  492. ShowMessage(" h: hour\n");
  493. ShowMessage(" mn: minute\n");
  494. ShowMessage(" s: second\n");
  495. ShowMessage(" <example> banadd testname +1m-2mn1s-6y\n");
  496. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  497. ShowMessage(" and 6 years at the same time.\n");
  498. ShowMessage("NOTE: If you modify the final date of a non-banished account,\n");
  499. ShowMessage(" you fix the final date to (actual time +- adjustments)\n");
  500. } else if (strcmp(command, "banset") == 0) {
  501. ShowMessage("banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  502. ShowMessage(" Changes the final date of a banishment of an account.\n");
  503. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  504. ShowMessage("banset <account_name> 0\n");
  505. ShowMessage(" Set a non-banished account (0 = unbanished).\n");
  506. } else if (strcmp(command, "block") == 0) {
  507. ShowMessage("block <account name>\n");
  508. ShowMessage(" Set state 5 (You have been blocked by the GM Team) to an account.\n");
  509. ShowMessage(" This command works like state <account_name> 5.\n");
  510. } else if (strcmp(command, "check") == 0) {
  511. ShowMessage("check <account_name> <password>\n");
  512. ShowMessage(" Check the validity of a password for an account.\n");
  513. ShowMessage(" NOTE: Server will never send back a password.\n");
  514. ShowMessage(" It's the only method you have to know if a password is correct.\n");
  515. ShowMessage(" The other method is to have a ('physical') access to the accounts file.\n");
  516. } else if (strcmp(command, "create") == 0) {
  517. ShowMessage("create <account_name> <sex> <email> <password>\n");
  518. ShowMessage(" Like the 'add' command, but with e-mail moreover.\n");
  519. ShowMessage(" <example> create testname Male my@mail.com testpass\n");
  520. } else if (strcmp(command, "delete") == 0) {
  521. ShowMessage("del <account name>\n");
  522. ShowMessage(" Remove an account.\n");
  523. ShowMessage(" This order requires confirmation. After confirmation, the account is deleted.\n");
  524. } else if (strcmp(command, "email") == 0) {
  525. ShowMessage("email <account_name> <email>\n");
  526. ShowMessage(" Modify the e-mail of an account.\n");
  527. } else if (strcmp(command, "getcount") == 0) {
  528. ShowMessage("getcount\n");
  529. ShowMessage(" Give the number of players online on all char-servers.\n");
  530. } else if (strcmp(command, "gm") == 0) {
  531. ShowMessage("gm <account_name> [GM_level]\n");
  532. ShowMessage(" Modify the GM level of an account.\n");
  533. ShowMessage(" Default value remove GM level (GM level = 0).\n");
  534. ShowMessage(" <example> gm testname 80\n");
  535. } else if (strcmp(command, "id") == 0) {
  536. ShowMessage("id <account name>\n");
  537. ShowMessage(" Give the id of an account.\n");
  538. } else if (strcmp(command, "info") == 0) {
  539. ShowMessage("info <account_id>\n");
  540. ShowMessage(" Display complete information of an account.\n");
  541. } else if (strcmp(command, "kami") == 0) {
  542. ShowMessage("kami <message>\n");
  543. ShowMessage(" Sends a broadcast message on all map-server (in yellow).\n");
  544. } else if (strcmp(command, "kamib") == 0) {
  545. ShowMessage("kamib <message>\n");
  546. ShowMessage(" Sends a broadcast message on all map-server (in blue).\n");
  547. } else if (strcmp(command, "list") == 0) {
  548. ShowMessage("list/ls [start_id [end_id]]\n");
  549. ShowMessage(" Display a list of accounts.\n");
  550. ShowMessage(" 'start_id', 'end_id': indicate end and start identifiers.\n");
  551. ShowMessage(" Research by name is not possible with this command.\n");
  552. ShowMessage(" <example> list 10 9999999\n");
  553. } else if (strcmp(command, "listban") == 0) {
  554. ShowMessage("listBan/lsBan [start_id [end_id]]\n");
  555. ShowMessage(" Like list/ls, but only for accounts with state or banished.\n");
  556. } else if (strcmp(command, "listgm") == 0) {
  557. ShowMessage("listGM/lsGM [start_id [end_id]]\n");
  558. ShowMessage(" Like list/ls, but only for GM accounts.\n");
  559. } else if (strcmp(command, "listok") == 0) {
  560. ShowMessage("listOK/lsOK [start_id [end_id]]\n");
  561. ShowMessage(" Like list/ls, but only for accounts without state and not banished.\n");
  562. } else if (strcmp(command, "memo") == 0) {
  563. ShowMessage("memo <account_name> <memo>\n");
  564. ShowMessage(" Modify the memo of an account.\n");
  565. ShowMessage(" 'memo': it can have until 253 characters (with spaces or not).\n");
  566. } else if (strcmp(command, "name") == 0) {
  567. ShowMessage("name <account_id>\n");
  568. ShowMessage(" Give the name of an account.\n");
  569. } else if (strcmp(command, "password") == 0) {
  570. ShowMessage("passwd <account_name> <new_password>\n");
  571. ShowMessage(" Change the password of an account.\n");
  572. ShowMessage(" When new password is omitted,\n");
  573. ShowMessage(" the input is done without displaying of the pressed keys.\n");
  574. } else if (strcmp(command, "reloadgm") == 0) {
  575. ShowMessage("reloadGM\n");
  576. ShowMessage(" Reload GM configuration file\n");
  577. } else if (strcmp(command, "search") == 0) {
  578. ShowMessage("search <expression>\n");
  579. ShowMessage(" Seek accounts.\n");
  580. ShowMessage(" Displays the accounts whose names correspond.\n");
  581. // ShowMessage("search -r/-e/--expr/--regex <expression>\n");
  582. // ShowMessage(" Seek accounts by regular expression.\n");
  583. // ShowMessage(" Displays the accounts whose names correspond.\n");
  584. } else if (strcmp(command, "sex") == 0) {
  585. ShowMessage("sex <account_name> <sex>\n");
  586. ShowMessage(" Modify the sex of an account.\n");
  587. ShowMessage(" <example> sex testname Male\n");
  588. } else if (strcmp(command, "state") == 0) {
  589. ShowMessage("state <account_name> <new_state> <error_message_#7>\n");
  590. ShowMessage(" Change the state of an account.\n");
  591. ShowMessage(" 'new_state': state is the state of the packet 0x006a + 1.\n");
  592. ShowMessage(" The possibilities are:\n");
  593. ShowMessage(" 0 = Account ok\n");
  594. ShowMessage(" 1 = Unregistered ID\n");
  595. ShowMessage(" 2 = Incorrect Password\n");
  596. ShowMessage(" 3 = This ID is expired\n");
  597. ShowMessage(" 4 = Rejected from Server\n");
  598. ShowMessage(" 5 = You have been blocked by the GM Team\n");
  599. ShowMessage(" 6 = Your Game's EXE file is not the latest version\n");
  600. ShowMessage(" 7 = You are Prohibited to log in until...\n");
  601. ShowMessage(" 8 = Server is jammed due to over populated\n");
  602. ShowMessage(" 9 = No MSG\n");
  603. ShowMessage(" 100 = This ID has been totally erased\n");
  604. ShowMessage(" all other values are 'No MSG', then use state 9 please.\n");
  605. ShowMessage(" 'error_message_#7': message of the code error 6\n");
  606. ShowMessage(" = Your are Prohibited to log in until... (packet 0x006a)\n");
  607. } else if (strcmp(command, "timeadd") == 0) {
  608. ShowMessage("timeadd <account_name> <modifier>\n");
  609. ShowMessage(" Adds or substracts time from the validity limit of an account.\n");
  610. ShowMessage(" Modifier is done as follows:\n");
  611. ShowMessage(" Adjustment value (-1, 1, +1, etc...)\n");
  612. ShowMessage(" Modified element:\n");
  613. ShowMessage(" a or y: year\n");
  614. ShowMessage(" m: month\n");
  615. ShowMessage(" j or d: day\n");
  616. ShowMessage(" h: hour\n");
  617. ShowMessage(" mn: minute\n");
  618. ShowMessage(" s: second\n");
  619. ShowMessage(" <example> timeadd testname +1m-2mn1s-6y\n");
  620. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  621. ShowMessage(" and 6 years at the same time.\n");
  622. ShowMessage("NOTE: You can not modify a unlimited validity limit.\n");
  623. ShowMessage(" If you want modify it, you want probably create a limited validity limit.\n");
  624. ShowMessage(" So, at first, you must set the validity limit to a date/time.\n");
  625. } else if (strcmp(command, "timeadd") == 0) {
  626. ShowMessage("timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  627. ShowMessage(" Changes the validity limit of an account.\n");
  628. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  629. ShowMessage("timeset <account_name> 0\n");
  630. ShowMessage(" Gives an unlimited validity limit (0 = unlimited).\n");
  631. } else if (strcmp(command, "unban") == 0) {
  632. ShowMessage("unban/unbanish <account name>\n");
  633. ShowMessage(" Remove the banishment of an account.\n");
  634. ShowMessage(" This command works like banset <account_name> 0.\n");
  635. } else if (strcmp(command, "unblock") == 0) {
  636. ShowMessage("unblock <account name>\n");
  637. ShowMessage(" Set state 0 (Account ok) to an account.\n");
  638. ShowMessage(" This command works like state <account_name> 0.\n");
  639. } else if (strcmp(command, "version") == 0) {
  640. ShowMessage("version\n");
  641. ShowMessage(" Display the version of the login-server.\n");
  642. } else if (strcmp(command, "who") == 0) {
  643. ShowMessage("who <account name>\n");
  644. ShowMessage(" Displays complete information of an account.\n");
  645. // quit
  646. } else if (strcmp(command, "quit") == 0 ||
  647. strcmp(command, "exit") == 0 ||
  648. strcmp(command, "end") == 0) {
  649. ShowMessage("quit/end/exit\n");
  650. ShowMessage(" End of the program of administration.\n");
  651. // unknown command
  652. } else {
  653. if (strlen(command) > 0)
  654. ShowMessage("Unknown command [%s] for help. Displaying of all commands.\n", command);
  655. ShowMessage(" aide/help/? -- Display this help\n");
  656. ShowMessage(" aide/help/? [command] -- Display the help of the command\n");
  657. ShowMessage(" add <account_name> <sex> <password> -- Create an account with default email\n");
  658. ShowMessage(" ban/banish yyyy/mm/dd hh:mm:ss <account name> -- Change final date of a ban\n");
  659. ShowMessage(" banadd/ba <account_name> <modifier> -- Add or substract time from the final\n");
  660. ShowMessage(" example: ba apple +1m-2mn1s-2y date of a banishment of an account\n");
  661. ShowMessage(" banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban\n");
  662. ShowMessage(" banset/bs <account_name> 0 -- Un-banish an account\n");
  663. ShowMessage(" block <account name> -- Set state 5 (blocked by the GM Team) to an account\n");
  664. ShowMessage(" check <account_name> <password> -- Check the validity of a password\n");
  665. ShowMessage(" create <account_name> <sex> <email> <passwrd> -- Create an account with email\n");
  666. ShowMessage(" del <account name> -- Remove an account\n");
  667. ShowMessage(" email <account_name> <email> -- Modify an email of an account\n");
  668. ShowMessage(" getcount -- Give the number of players online\n");
  669. ShowMessage(" gm <account_name> [GM_level] -- Modify the GM level of an account\n");
  670. ShowMessage(" id <account name> -- Give the id of an account\n");
  671. ShowMessage(" info <account_id> -- Display all information of an account\n");
  672. ShowMessage(" kami <message> -- Sends a broadcast message (in yellow)\n");
  673. ShowMessage(" kamib <message> -- Sends a broadcast message (in blue)\n");
  674. ShowMessage(" list/ls [First_id [Last_id]] -- Display a list of accounts\n");
  675. ShowMessage(" listBan/lsBan [First_id [Last_id] ] -- Display a list of accounts\n");
  676. ShowMessage(" with state or banished\n");
  677. ShowMessage(" listGM/lsGM [First_id [Last_id]] -- Display a list of GM accounts\n");
  678. ShowMessage(" listOK/lsOK [First_id [Last_id] ] -- Display a list of accounts\n");
  679. ShowMessage(" without state and not banished\n");
  680. ShowMessage(" memo <account_name> <memo> -- Modify the memo of an account\n");
  681. ShowMessage(" name <account_id> -- Give the name of an account\n");
  682. ShowMessage(" passwd <account_name> <new_password> -- Change the password of an account\n");
  683. ShowMessage(" quit/end/exit -- End of the program of administation\n");
  684. ShowMessage(" reloadGM -- Reload GM configuration file\n");
  685. ShowMessage(" search <expression> -- Seek accounts\n");
  686. // ShowMessage(" search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression\n");
  687. ShowMessage(" sex <nomcompte> <sexe> -- Modify the sex of an account\n");
  688. ShowMessage(" state <account_name> <new_state> <error_message_#7> -- Change the state\n");
  689. ShowMessage(" timeadd/ta <account_name> <modifier> -- Add or substract time from the\n");
  690. ShowMessage(" example: ta apple +1m-2mn1s-2y validity limit of an account\n");
  691. ShowMessage(" timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit\n");
  692. ShowMessage(" timeset/ts <account_name> 0 -- Give a unlimited validity limit\n");
  693. ShowMessage(" unban/unbanish <account name> -- Remove the banishment of an account\n");
  694. ShowMessage(" unblock <account name> -- Set state 0 (Account ok) to an account\n");
  695. ShowMessage(" version -- Gives the version of the login-server\n");
  696. ShowMessage(" who <account name> -- Display all information of an account\n");
  697. ShowMessage(" who <account name> -- Display all information of an account\n");
  698. ShowMessage(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n");
  699. }
  700. }
  701. //-----------------------------
  702. // Sub-function: add an account
  703. //-----------------------------
  704. int addaccount(char* param, int emailflag)
  705. {
  706. char name[1023], sex[1023], email[1023], password[1023];
  707. // int i;
  708. WFIFOHEAD(login_fd,91);
  709. memset(name, '\0', sizeof(name));
  710. memset(sex, '\0', sizeof(sex));
  711. memset(email, '\0', sizeof(email));
  712. memset(password, '\0', sizeof(password));
  713. if (emailflag == 0) { // add command
  714. if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, sex, password) < 2 && // password can be void
  715. sscanf(param, "'%[^']' %s %[^\r\n]", name, sex, password) < 2 && // password can be void
  716. sscanf(param, "%s %s %[^\r\n]", name, sex, password) < 2) { // password can be void
  717. ShowMessage("Please input an account name, a sex and a password.\n");
  718. ShowMessage("<example> add testname Male testpass\n");
  719. ladmin_log("Incomplete parameters to create an account ('add' command).\n");
  720. return 136;
  721. }
  722. strcpy(email, "a@a.com"); // default email
  723. } else { // 1: create command
  724. if (sscanf(param, "\"%[^\"]\" %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
  725. sscanf(param, "'%[^']' %s %s %[^\r\n]", name, sex, email, password) < 3 && // password can be void
  726. sscanf(param, "%s %s %s %[^\r\n]", name, sex, email, password) < 3) { // password can be void
  727. ShowMessage("Please input an account name, a sex and a password.\n");
  728. ShowMessage("<example> create testname Male my@mail.com testpass\n");
  729. ladmin_log("Incomplete parameters to create an account ('create' command).\n");
  730. return 136;
  731. }
  732. }
  733. if (verify_accountname(name) == 0) {
  734. return 102;
  735. }
  736. sex[0] = TOUPPER(sex[0]);
  737. if (strchr("MF", sex[0]) == NULL) {
  738. ShowMessage("Illegal gender [%s]. Please input M or F.\n", sex);
  739. ladmin_log("Illegal gender [%s]. Please input M or F.\n", sex);
  740. return 103;
  741. }
  742. if (strlen(email) < 3) {
  743. ShowMessage("Email is too short [%s]. Please input a valid e-mail.\n", email);
  744. ladmin_log("Email is too short [%s]. Please input a valid e-mail.\n", email);
  745. return 109;
  746. }
  747. if (strlen(email) > 39) {
  748. ShowMessage("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
  749. ladmin_log("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
  750. return 109;
  751. }
  752. if (e_mail_check(email) == 0) {
  753. ShowMessage("Invalid email [%s]. Please input a valid e-mail.\n", email);
  754. ladmin_log("Invalid email [%s]. Please input a valid e-mail.\n", email);
  755. return 109;
  756. }
  757. if (strlen(password) == 0) {
  758. if (typepasswd(password) == 0)
  759. return 108;
  760. }
  761. if (verify_password(password) == 0)
  762. return 104;
  763. ladmin_log("Request to login-server to create an account.\n");
  764. WFIFOW(login_fd,0) = 0x7930;
  765. memcpy(WFIFOP(login_fd,2), name, 24);
  766. memcpy(WFIFOP(login_fd,26), password, 24);
  767. WFIFOB(login_fd,50) = sex[0];
  768. memcpy(WFIFOP(login_fd,51), email, 40);
  769. WFIFOSET(login_fd,91);
  770. bytes_to_read = 1;
  771. return 0;
  772. }
  773. //---------------------------------------------------------------------------------
  774. // Sub-function: Add/substract time to the final date of a banishment of an account
  775. //---------------------------------------------------------------------------------
  776. int banaddaccount(char* param)
  777. {
  778. char name[1023], modif[1023];
  779. int year, month, day, hour, minute, second;
  780. char * p_modif;
  781. int value, i;
  782. WFIFOHEAD(login_fd,38);
  783. memset(name, '\0', sizeof(name));
  784. memset(modif, '\0', sizeof(modif));
  785. year = month = day = hour = minute = second = 0;
  786. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
  787. sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
  788. sscanf(param, "%s %[^\r\n]", name, modif) < 2) {
  789. ShowMessage("Please input an account name and a modifier.\n");
  790. ShowMessage(" <example>: banadd testname +1m-2mn1s-6y\n");
  791. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  792. ShowMessage(" and 6 years at the same time.\n");
  793. ladmin_log("Incomplete parameters to modify the ban date/time of an account ('banadd' command).\n");
  794. return 136;
  795. }
  796. if (verify_accountname(name) == 0) {
  797. return 102;
  798. }
  799. // lowercase for modif
  800. for (i = 0; modif[i]; i++)
  801. modif[i] = TOLOWER(modif[i]);
  802. p_modif = modif;
  803. while (strlen(p_modif) > 0) {
  804. value = atoi(p_modif);
  805. if (value == 0) {
  806. p_modif++;
  807. } else {
  808. if (p_modif[0] == '-' || p_modif[0] == '+')
  809. p_modif++;
  810. while (strlen(p_modif) > 0 && p_modif[0] >= '0' && p_modif[0] <= '9') {
  811. p_modif++;
  812. }
  813. if (p_modif[0] == 's') {
  814. second = value;
  815. p_modif++;
  816. } else if (p_modif[0] == 'm' && p_modif[1] == 'n') {
  817. minute = value;
  818. p_modif += 2;
  819. } else if (p_modif[0] == 'h') {
  820. hour = value;
  821. p_modif++;
  822. } else if (p_modif[0] == 'd' || p_modif[0] == 'j') {
  823. day = value;
  824. p_modif += 2;
  825. } else if (p_modif[0] == 'm') {
  826. month = value;
  827. p_modif++;
  828. } else if (p_modif[0] == 'y' || p_modif[0] == 'a') {
  829. year = value;
  830. p_modif++;
  831. } else {
  832. p_modif++;
  833. }
  834. }
  835. }
  836. ShowMessage(" year: %d\n", year);
  837. ShowMessage(" month: %d\n", month);
  838. ShowMessage(" day: %d\n", day);
  839. ShowMessage(" hour: %d\n", hour);
  840. ShowMessage(" minute: %d\n", minute);
  841. ShowMessage(" second: %d\n", second);
  842. if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) {
  843. ShowMessage("Please give an adjustment with this command:\n");
  844. ShowMessage(" Adjustment value (-1, 1, +1, etc...)\n");
  845. ShowMessage(" Modified element:\n");
  846. ShowMessage(" a or y: year\n");
  847. ShowMessage(" m: month\n");
  848. ShowMessage(" j or d: day\n");
  849. ShowMessage(" h: hour\n");
  850. ShowMessage(" mn: minute\n");
  851. ShowMessage(" s: second\n");
  852. ShowMessage(" <example> banadd testname +1m-2mn1s-6y\n");
  853. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  854. ShowMessage(" and 6 years at the same time.\n");
  855. ladmin_log("No adjustment isn't an adjustment ('banadd' command).\n");
  856. return 137;
  857. }
  858. if (year > 127 || year < -127) {
  859. ShowMessage("Please give a correct adjustment for the years (from -127 to 127).\n");
  860. ladmin_log("Abnormal adjustment for the year ('banadd' command).\n");
  861. return 137;
  862. }
  863. if (month > 255 || month < -255) {
  864. ShowMessage("Please give a correct adjustment for the months (from -255 to 255).\n");
  865. ladmin_log("Abnormal adjustment for the month ('banadd' command).\n");
  866. return 137;
  867. }
  868. if (day > 32767 || day < -32767) {
  869. ShowMessage("Please give a correct adjustment for the days (from -32767 to 32767).\n");
  870. ladmin_log("Abnormal adjustment for the days ('banadd' command).\n");
  871. return 137;
  872. }
  873. if (hour > 32767 || hour < -32767) {
  874. ShowMessage("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
  875. ladmin_log("Abnormal adjustment for the hours ('banadd' command).\n");
  876. return 137;
  877. }
  878. if (minute > 32767 || minute < -32767) {
  879. ShowMessage("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
  880. ladmin_log("Abnormal adjustment for the minutes ('banadd' command).\n");
  881. return 137;
  882. }
  883. if (second > 32767 || second < -32767) {
  884. ShowMessage("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
  885. ladmin_log("Abnormal adjustment for the seconds ('banadd' command).\n");
  886. return 137;
  887. }
  888. ladmin_log("Request to login-server to modify a ban date/time.\n");
  889. WFIFOW(login_fd,0) = 0x794c;
  890. memcpy(WFIFOP(login_fd,2), name, 24);
  891. WFIFOW(login_fd,26) = (short)year;
  892. WFIFOW(login_fd,28) = (short)month;
  893. WFIFOW(login_fd,30) = (short)day;
  894. WFIFOW(login_fd,32) = (short)hour;
  895. WFIFOW(login_fd,34) = (short)minute;
  896. WFIFOW(login_fd,36) = (short)second;
  897. WFIFOSET(login_fd,38);
  898. bytes_to_read = 1;
  899. return 0;
  900. }
  901. //-----------------------------------------------------------------------
  902. // Sub-function of sub-function banaccount, unbanaccount or bansetaccount
  903. // Set the final date of a banishment of an account
  904. //-----------------------------------------------------------------------
  905. int bansetaccountsub(char* name, char* date, char* time)
  906. {
  907. int year, month, day, hour, minute, second;
  908. time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
  909. struct tm *tmtime;
  910. WFIFOHEAD(login_fd,30);
  911. year = month = day = hour = minute = second = 0;
  912. unban_time = 0;
  913. tmtime = localtime(&unban_time); // initialize
  914. if (verify_accountname(name) == 0) {
  915. return 102;
  916. }
  917. if (atoi(date) != 0 &&
  918. ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
  919. sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
  920. sscanf(date, "%d.%d.%d", &year, &month, &day) < 3) ||
  921. sscanf(time, "%d:%d:%d", &hour, &minute, &second) < 3))
  922. {
  923. ShowMessage("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
  924. ShowMessage("You can imput 0 instead of if you use 'banset' command.\n");
  925. ladmin_log("Invalid format for the date/time ('banset' or 'ban' command).\n");
  926. return 102;
  927. }
  928. if (atoi(date) == 0) {
  929. unban_time = 0;
  930. } else {
  931. if (year < 70) {
  932. year = year + 100;
  933. }
  934. if (year >= 1900) {
  935. year = year - 1900;
  936. }
  937. if (month < 1 || month > 12) {
  938. ShowMessage("Please give a correct value for the month (from 1 to 12).\n");
  939. ladmin_log("Invalid month for the date ('banset' or 'ban' command).\n");
  940. return 102;
  941. }
  942. month = month - 1;
  943. if (day < 1 || day > 31) {
  944. ShowMessage("Please give a correct value for the day (from 1 to 31).\n");
  945. ladmin_log("Invalid day for the date ('banset' or 'ban' command).\n");
  946. return 102;
  947. }
  948. if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) ||
  949. (month == 1 && day > 29)) {
  950. ShowMessage("Please give a correct value for a day of this month (%d).\n", month);
  951. ladmin_log("Invalid day for this month ('banset' or 'ban' command).\n");
  952. return 102;
  953. }
  954. if (hour < 0 || hour > 23) {
  955. ShowMessage("Please give a correct value for the hour (from 0 to 23).\n");
  956. ladmin_log("Invalid hour for the time ('banset' or 'ban' command).\n");
  957. return 102;
  958. }
  959. if (minute < 0 || minute > 59) {
  960. ShowMessage("Please give a correct value for the minutes (from 0 to 59).\n");
  961. ladmin_log("Invalid minute for the time ('banset' or 'ban' command).\n");
  962. return 102;
  963. }
  964. if (second < 0 || second > 59) {
  965. ShowMessage("Please give a correct value for the seconds (from 0 to 59).\n");
  966. ladmin_log("Invalid second for the time ('banset' or 'ban' command).\n");
  967. return 102;
  968. }
  969. tmtime->tm_year = year;
  970. tmtime->tm_mon = month;
  971. tmtime->tm_mday = day;
  972. tmtime->tm_hour = hour;
  973. tmtime->tm_min = minute;
  974. tmtime->tm_sec = second;
  975. tmtime->tm_isdst = -1; // -1: no winter/summer time modification
  976. unban_time = mktime(tmtime);
  977. if (unban_time == -1) {
  978. ShowMessage("Invalid date.\n");
  979. ShowMessage("Please input a date and a time (format: yyyy/mm/dd hh:mm:ss).\n");
  980. ShowMessage("You can imput 0 instead of if you use 'banset' command.\n");
  981. ladmin_log("Invalid date. ('banset' or 'ban' command).\n");
  982. return 102;
  983. }
  984. }
  985. ladmin_log("Request to login-server to set a ban.\n");
  986. WFIFOW(login_fd,0) = 0x794a;
  987. memcpy(WFIFOP(login_fd,2), name, 24);
  988. WFIFOL(login_fd,26) = (int)unban_time;
  989. WFIFOSET(login_fd,30);
  990. bytes_to_read = 1;
  991. return 0;
  992. }
  993. //---------------------------------------------------------------------
  994. // Sub-function: Set the final date of a banishment of an account (ban)
  995. //---------------------------------------------------------------------
  996. int banaccount(char* param)
  997. {
  998. char name[1023], date[1023], time[1023];
  999. memset(name, '\0', sizeof(name));
  1000. memset(date, '\0', sizeof(date));
  1001. memset(time, '\0', sizeof(time));
  1002. if (sscanf(param, "%s %s \"%[^\"]\"", date, time, name) < 3 &&
  1003. sscanf(param, "%s %s '%[^']'", date, time, name) < 3 &&
  1004. sscanf(param, "%s %s %[^\r\n]", date, time, name) < 3) {
  1005. ShowMessage("Please input an account name, a date and a hour.\n");
  1006. ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  1007. ShowMessage(" banset <account_name> 0 (0 = un-banished)\n");
  1008. ShowMessage(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
  1009. ShowMessage(" unban/unbanish <account name>\n");
  1010. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  1011. ladmin_log("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
  1012. return 136;
  1013. }
  1014. return bansetaccountsub(name, date, time);
  1015. }
  1016. //------------------------------------------------------------------------
  1017. // Sub-function: Set the final date of a banishment of an account (banset)
  1018. //------------------------------------------------------------------------
  1019. int bansetaccount(char* param)
  1020. {
  1021. char name[1023], date[1023], time[1023];
  1022. memset(name, '\0', sizeof(name));
  1023. memset(date, '\0', sizeof(date));
  1024. memset(time, '\0', sizeof(time));
  1025. if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
  1026. sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
  1027. sscanf(param, "%s %s %[^\r\n]", name, date, time) < 2) { // if date = 0, time can be void
  1028. ShowMessage("Please input an account name, a date and a hour.\n");
  1029. ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  1030. ShowMessage(" banset <account_name> 0 (0 = un-banished)\n");
  1031. ShowMessage(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
  1032. ShowMessage(" unban/unbanish <account name>\n");
  1033. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  1034. ladmin_log("Incomplete parameters to set a ban ('banset' or 'ban' command).\n");
  1035. return 136;
  1036. }
  1037. if (time[0] == '\0')
  1038. strcpy(time, "23:59:59");
  1039. return bansetaccountsub(name, date, time);
  1040. }
  1041. //-------------------------------------------------
  1042. // Sub-function: unbanishment of an account (unban)
  1043. //-------------------------------------------------
  1044. int unbanaccount(char* param)
  1045. {
  1046. char name[1023];
  1047. memset(name, '\0', sizeof(name));
  1048. if (strlen(param) == 0 ||
  1049. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1050. sscanf(param, "'%[^']'", name) < 1 &&
  1051. sscanf(param, "%[^\r\n]", name) < 1) ||
  1052. strlen(name) == 0)
  1053. {
  1054. ShowMessage("Please input an account name.\n");
  1055. ShowMessage("<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  1056. ShowMessage(" banset <account_name> 0 (0 = un-banished)\n");
  1057. ShowMessage(" ban/banish yyyy/mm/dd hh:mm:ss <account name>\n");
  1058. ShowMessage(" unban/unbanish <account name>\n");
  1059. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  1060. ladmin_log("Incomplete parameters to set a ban ('unban' command).\n");
  1061. return 136;
  1062. }
  1063. return bansetaccountsub(name, "0", "");
  1064. }
  1065. //---------------------------------------------------------
  1066. // Sub-function: Asking to check the validity of a password
  1067. // (Note: never send back a password with login-server!! security of passwords)
  1068. //---------------------------------------------------------
  1069. int checkaccount(char* param)
  1070. {
  1071. char name[1023], password[1023];
  1072. WFIFOHEAD(login_fd,50);
  1073. memset(name, '\0', sizeof(name));
  1074. memset(password, '\0', sizeof(password));
  1075. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 && // password can be void
  1076. sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 && // password can be void
  1077. sscanf(param, "%s %[^\r\n]", name, password) < 1) { // password can be void
  1078. ShowMessage("Please input an account name.\n");
  1079. ShowMessage("<example> check testname password\n");
  1080. ladmin_log("Incomplete parameters to check the password of an account ('check' command).\n");
  1081. return 136;
  1082. }
  1083. if (verify_accountname(name) == 0) {
  1084. return 102;
  1085. }
  1086. if (strlen(password) == 0) {
  1087. if (typepasswd(password) == 0)
  1088. return 134;
  1089. }
  1090. if (verify_password(password) == 0)
  1091. return 131;
  1092. ladmin_log("Request to login-server to check a password.\n");
  1093. WFIFOW(login_fd,0) = 0x793a;
  1094. memcpy(WFIFOP(login_fd,2), name, 24);
  1095. memcpy(WFIFOP(login_fd,26), password, 24);
  1096. WFIFOSET(login_fd,50);
  1097. bytes_to_read = 1;
  1098. return 0;
  1099. }
  1100. //------------------------------------------------
  1101. // Sub-function: Asking for deletion of an account
  1102. //------------------------------------------------
  1103. int delaccount(char* param)
  1104. {
  1105. char name[1023];
  1106. char letter;
  1107. char confirm[1023];
  1108. int i;
  1109. WFIFOHEAD(login_fd,26);
  1110. memset(name, '\0', sizeof(name));
  1111. if (strlen(param) == 0 ||
  1112. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1113. sscanf(param, "'%[^']'", name) < 1 &&
  1114. sscanf(param, "%[^\r\n]", name) < 1) ||
  1115. strlen(name) == 0)
  1116. {
  1117. ShowMessage("Please input an account name.\n");
  1118. ShowMessage("<example> del testnametodelete\n");
  1119. ladmin_log("No name given to delete an account ('delete' command).\n");
  1120. return 136;
  1121. }
  1122. if (verify_accountname(name) == 0) {
  1123. return 102;
  1124. }
  1125. memset(confirm, '\0', sizeof(confirm));
  1126. while (confirm[0] != 'n' && confirm[0] != 'y')
  1127. {
  1128. ShowMessage("\033[1;36m ** Are you really sure to DELETE account [$userid]? (y/n) > \033[0m");
  1129. fflush(stdout);
  1130. memset(confirm, '\0', sizeof(confirm));
  1131. i = 0;
  1132. while ((letter = getchar()) != '\n')
  1133. confirm[i++] = letter;
  1134. }
  1135. if (confirm[0] == 'n') {
  1136. ShowMessage("Deletion canceled.\n");
  1137. ladmin_log("Deletion canceled by user ('delete' command).\n");
  1138. return 121;
  1139. }
  1140. ladmin_log("Request to login-server to delete an acount.\n");
  1141. WFIFOW(login_fd,0) = 0x7932;
  1142. memcpy(WFIFOP(login_fd,2), name, 24);
  1143. WFIFOSET(login_fd,26);
  1144. bytes_to_read = 1;
  1145. return 0;
  1146. }
  1147. //----------------------------------------------------------
  1148. // Sub-function: Asking to modification of an account e-mail
  1149. //----------------------------------------------------------
  1150. int changeemail(char* param)
  1151. {
  1152. char name[1023], email[1023];
  1153. WFIFOHEAD(login_fd,66);
  1154. memset(name, '\0', sizeof(name));
  1155. memset(email, '\0', sizeof(email));
  1156. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, email) < 2 &&
  1157. sscanf(param, "'%[^']' %[^\r\n]", name, email) < 2 &&
  1158. sscanf(param, "%s %[^\r\n]", name, email) < 2) {
  1159. ShowMessage("Please input an account name and an email.\n");
  1160. ShowMessage("<example> email testname newemail\n");
  1161. ladmin_log("Incomplete parameters to change the email of an account ('email' command).\n");
  1162. return 136;
  1163. }
  1164. if (verify_accountname(name) == 0) {
  1165. return 102;
  1166. }
  1167. if (strlen(email) < 3) {
  1168. ShowMessage("Email is too short [%s]. Please input a valid e-mail.\n", email);
  1169. ladmin_log("Email is too short [%s]. Please input a valid e-mail.\n", email);
  1170. return 109;
  1171. }
  1172. if (strlen(email) > 39) {
  1173. ShowMessage("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
  1174. ladmin_log("Email is too long [%s]. Please input an e-mail with 39 bytes at the most.\n", email);
  1175. return 109;
  1176. }
  1177. if (e_mail_check(email) == 0) {
  1178. ShowMessage("Invalid email [%s]. Please input a valid e-mail.\n", email);
  1179. ladmin_log("Invalid email [%s]. Please input a valid e-mail.\n", email);
  1180. return 109;
  1181. }
  1182. ladmin_log("Request to login-server to change an email.\n");
  1183. WFIFOW(login_fd,0) = 0x7940;
  1184. memcpy(WFIFOP(login_fd,2), name, 24);
  1185. memcpy(WFIFOP(login_fd,26), email, 40);
  1186. WFIFOSET(login_fd,66);
  1187. bytes_to_read = 1;
  1188. return 0;
  1189. }
  1190. //-----------------------------------------------------
  1191. // Sub-function: Asking of the number of online players
  1192. //-----------------------------------------------------
  1193. int getlogincount(void)
  1194. {
  1195. WFIFOHEAD(login_fd,2);
  1196. ladmin_log("Request to login-server to obtain the # of online players.\n");
  1197. WFIFOW(login_fd,0) = 0x7938;
  1198. WFIFOSET(login_fd,2);
  1199. bytes_to_read = 1;
  1200. return 0;
  1201. }
  1202. //----------------------------------------------------------
  1203. // Sub-function: Asking to modify the GM level of an account
  1204. //----------------------------------------------------------
  1205. int changegmlevel(char* param)
  1206. {
  1207. char name[1023];
  1208. int GM_level;
  1209. WFIFOHEAD(login_fd,27);
  1210. memset(name, '\0', sizeof(name));
  1211. GM_level = 0;
  1212. if (sscanf(param, "\"%[^\"]\" %d", name, &GM_level) < 1 &&
  1213. sscanf(param, "'%[^']' %d", name, &GM_level) < 1 &&
  1214. sscanf(param, "%s %d", name, &GM_level) < 1) {
  1215. ShowMessage("Please input an account name and a GM level.\n");
  1216. ShowMessage("<example> gm testname 80\n");
  1217. ladmin_log("Incomplete parameters to change the GM level of an account ('gm' command).\n");
  1218. return 136;
  1219. }
  1220. if (verify_accountname(name) == 0) {
  1221. return 102;
  1222. }
  1223. if (GM_level < 0 || GM_level > 99) {
  1224. ShowMessage("Illegal GM level [%d]. Please input a value from 0 to 99.\n", GM_level);
  1225. ladmin_log("Illegal GM level [%d]. The value can be from 0 to 99.\n", GM_level);
  1226. return 103;
  1227. }
  1228. ladmin_log("Request to login-server to change a GM level.\n");
  1229. WFIFOW(login_fd,0) = 0x793e;
  1230. memcpy(WFIFOP(login_fd,2), name, 24);
  1231. WFIFOB(login_fd,26) = GM_level;
  1232. WFIFOSET(login_fd,27);
  1233. bytes_to_read = 1;
  1234. return 0;
  1235. }
  1236. //---------------------------------------------
  1237. // Sub-function: Asking to obtain an account id
  1238. //---------------------------------------------
  1239. int idaccount(char* param)
  1240. {
  1241. char name[1023];
  1242. WFIFOHEAD(login_fd,26);
  1243. memset(name, '\0', sizeof(name));
  1244. if (strlen(param) == 0 ||
  1245. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1246. sscanf(param, "'%[^']'", name) < 1 &&
  1247. sscanf(param, "%[^\r\n]", name) < 1) ||
  1248. strlen(name) == 0)
  1249. {
  1250. ShowMessage("Please input an account name.\n");
  1251. ShowMessage("<example> id testname\n");
  1252. ladmin_log("No name given to search an account id ('id' command).\n");
  1253. return 136;
  1254. }
  1255. if (verify_accountname(name) == 0) {
  1256. return 102;
  1257. }
  1258. ladmin_log("Request to login-server to know an account id.\n");
  1259. WFIFOW(login_fd,0) = 0x7944;
  1260. memcpy(WFIFOP(login_fd,2), name, 24);
  1261. WFIFOSET(login_fd,26);
  1262. bytes_to_read = 1;
  1263. return 0;
  1264. }
  1265. //----------------------------------------------------------------------------
  1266. // Sub-function: Asking to displaying information about an account (by its id)
  1267. //----------------------------------------------------------------------------
  1268. int infoaccount(int account_id)
  1269. {
  1270. WFIFOHEAD(login_fd,6);
  1271. if (account_id < 0) {
  1272. ShowMessage("Please input a positive value for the id.\n");
  1273. ladmin_log("Negative value was given to found the account.\n");
  1274. return 136;
  1275. }
  1276. ladmin_log("Request to login-server to obtain information about an account (by its id).\n");
  1277. WFIFOW(login_fd,0) = 0x7954;
  1278. WFIFOL(login_fd,2) = account_id;
  1279. WFIFOSET(login_fd,6);
  1280. bytes_to_read = 1;
  1281. return 0;
  1282. }
  1283. //---------------------------------------
  1284. // Sub-function: Send a broadcast message
  1285. //---------------------------------------
  1286. int sendbroadcast(short type, char* message)
  1287. {
  1288. int len = strlen(message);
  1289. WFIFOHEAD(login_fd,9+len);
  1290. if (len == 0) {
  1291. ShowMessage("Please input a message.\n");
  1292. if (type == 0) {
  1293. ShowMessage("<example> kami a message\n");
  1294. } else {
  1295. ShowMessage("<example> kamib a message\n");
  1296. }
  1297. ladmin_log("The message is void ('kami(b)' command).\n");
  1298. return 136;
  1299. }
  1300. len++; //+'\0'
  1301. WFIFOW(login_fd,0) = 0x794e;
  1302. WFIFOW(login_fd,2) = type;
  1303. WFIFOL(login_fd,4) = len;
  1304. memcpy(WFIFOP(login_fd,8), message, len);
  1305. WFIFOSET(login_fd,8+len);
  1306. bytes_to_read = 1;
  1307. return 0;
  1308. }
  1309. //--------------------------------------------------------
  1310. // Sub-function: Asking to Displaying of the accounts list
  1311. //--------------------------------------------------------
  1312. int listaccount(char* param, int type)
  1313. {
  1314. //int list_first, list_last, list_type; // parameter to display a list of accounts
  1315. int i;
  1316. WFIFOHEAD(login_fd,10);
  1317. list_type = type;
  1318. // set default values
  1319. list_first = 0;
  1320. list_last = 0;
  1321. if (list_type == 1) { // if listgm
  1322. // get all accounts = use default
  1323. } else if (list_type == 2) { // if search
  1324. for (i = 0; param[i]; i++)
  1325. param[i] = TOLOWER(param[i]);
  1326. // get all accounts = use default
  1327. } else if (list_type == 3) { // if listban
  1328. // get all accounts = use default
  1329. } else if (list_type == 4) { // if listok
  1330. // get all accounts = use default
  1331. } else { // if list (list_type == 0)
  1332. switch(sscanf(param, "%d %d", &list_first, &list_last)) {
  1333. case 0:
  1334. // get all accounts = use default
  1335. break;
  1336. case 1:
  1337. list_last = 0;
  1338. // use tests of the following value
  1339. default:
  1340. if (list_first < 0)
  1341. list_first = 0;
  1342. if (list_last < list_first || list_last < 0)
  1343. list_last = 0;
  1344. break;
  1345. }
  1346. }
  1347. ladmin_log("Request to login-server to obtain the list of accounts from %d to %d.\n", list_first, list_last);
  1348. WFIFOW(login_fd,0) = 0x7920;
  1349. WFIFOL(login_fd,2) = list_first;
  1350. WFIFOL(login_fd,6) = list_last;
  1351. WFIFOSET(login_fd,10);
  1352. bytes_to_read = 1;
  1353. // 0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
  1354. ShowMessage("account_id GM user_name sex count state\n");
  1355. ShowMessage("-------------------------------------------------------------------------------\n");
  1356. list_count = 0;
  1357. return 0;
  1358. }
  1359. //--------------------------------------------
  1360. // Sub-function: Asking to modify a memo field
  1361. //--------------------------------------------
  1362. int changememo(char* param)
  1363. {
  1364. char name[1023], memo[1023];
  1365. WFIFOHEAD(login_fd,28+255);
  1366. memset(name, '\0', sizeof(name));
  1367. memset(memo, '\0', sizeof(memo));
  1368. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, memo) < 1 && // memo can be void
  1369. sscanf(param, "'%[^']' %[^\r\n]", name, memo) < 1 && // memo can be void
  1370. sscanf(param, "%s %[^\r\n]", name, memo) < 1) { // memo can be void
  1371. ShowMessage("Please input an account name and a memo.\n");
  1372. ShowMessage("<example> memo testname new memo\n");
  1373. ladmin_log("Incomplete parameters to change the memo of an account ('email' command).\n");
  1374. return 136;
  1375. }
  1376. if (verify_accountname(name) == 0) {
  1377. return 102;
  1378. }
  1379. if (strlen(memo) > 254) {
  1380. ShowMessage("Memo is too long (%lu characters).\n", (unsigned long)strlen(memo));
  1381. ShowMessage("Please input a memo of 254 bytes at the maximum.\n");
  1382. ladmin_log("Email is too long (%d characters). Please input a memo of 254 bytes at the maximum.\n", strlen(memo));
  1383. return 102;
  1384. }
  1385. ladmin_log("Request to login-server to change a memo.\n");
  1386. WFIFOW(login_fd,0) = 0x7942;
  1387. memcpy(WFIFOP(login_fd,2), name, 24);
  1388. WFIFOW(login_fd,26) = strlen(memo);
  1389. if (strlen(memo) > 0)
  1390. memcpy(WFIFOP(login_fd,28), memo, strlen(memo));
  1391. WFIFOSET(login_fd,28+strlen(memo));
  1392. bytes_to_read = 1;
  1393. return 0;
  1394. }
  1395. //-----------------------------------------------
  1396. // Sub-function: Asking to obtain an account name
  1397. //-----------------------------------------------
  1398. int nameaccount(int id)
  1399. {
  1400. WFIFOHEAD(login_fd,6);
  1401. if (id < 0) {
  1402. ShowMessage("Please input a positive value for the id.\n");
  1403. ladmin_log("Negativ id given to search an account name ('name' command).\n");
  1404. return 136;
  1405. }
  1406. ladmin_log("Request to login-server to know an account name.\n");
  1407. WFIFOW(login_fd,0) = 0x7946;
  1408. WFIFOL(login_fd,2) = id;
  1409. WFIFOSET(login_fd,6);
  1410. bytes_to_read = 1;
  1411. return 0;
  1412. }
  1413. //------------------------------------------
  1414. // Sub-function: Asking to modify a password
  1415. // (Note: never send back a password with login-server!! security of passwords)
  1416. //------------------------------------------
  1417. int changepasswd(char* param)
  1418. {
  1419. char name[1023], password[1023];
  1420. WFIFOHEAD(login_fd,50);
  1421. memset(name, '\0', sizeof(name));
  1422. memset(password, '\0', sizeof(password));
  1423. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, password) < 1 &&
  1424. sscanf(param, "'%[^']' %[^\r\n]", name, password) < 1 &&
  1425. sscanf(param, "%s %[^\r\n]", name, password) < 1) {
  1426. ShowMessage("Please input an account name.\n");
  1427. ShowMessage("<example> passwd testname newpassword\n");
  1428. ladmin_log("Incomplete parameters to change the password of an account ('password' command).\n");
  1429. return 136;
  1430. }
  1431. if (verify_accountname(name) == 0) {
  1432. return 102;
  1433. }
  1434. if (strlen(password) == 0) {
  1435. if (typepasswd(password) == 0)
  1436. return 134;
  1437. }
  1438. if (verify_password(password) == 0)
  1439. return 131;
  1440. ladmin_log("Request to login-server to change a password.\n");
  1441. WFIFOW(login_fd,0) = 0x7934;
  1442. memcpy(WFIFOP(login_fd,2), name, 24);
  1443. memcpy(WFIFOP(login_fd,26), password, 24);
  1444. WFIFOSET(login_fd,50);
  1445. bytes_to_read = 1;
  1446. return 0;
  1447. }
  1448. //----------------------------------------------------------------------
  1449. // Sub-function: Request to login-server to reload GM configuration file
  1450. // this function have no answer
  1451. //----------------------------------------------------------------------
  1452. int reloadGM(void)
  1453. {
  1454. WFIFOHEAD(login_fd,2);
  1455. WFIFOW(login_fd,0) = 0x7955;
  1456. WFIFOSET(login_fd,2);
  1457. bytes_to_read = 0;
  1458. ladmin_log("Request to reload the GM configuration file sended.\n");
  1459. ShowMessage("Request to reload the GM configuration file sended.\n");
  1460. ShowMessage("Check the actual GM accounts (after reloading):\n");
  1461. listaccount(parameters, 1); // 1: to list only GM
  1462. return 180;
  1463. }
  1464. //-----------------------------------------------------
  1465. // Sub-function: Asking to modify the sex of an account
  1466. //-----------------------------------------------------
  1467. int changesex(char* param)
  1468. {
  1469. char name[1023], sex[1023];
  1470. WFIFOHEAD(login_fd,27);
  1471. memset(name, '\0', sizeof(name));
  1472. memset(sex, '\0', sizeof(sex));
  1473. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, sex) < 2 &&
  1474. sscanf(param, "'%[^']' %[^\r\n]", name, sex) < 2 &&
  1475. sscanf(param, "%s %[^\r\n]", name, sex) < 2) {
  1476. ShowMessage("Please input an account name and a sex.\n");
  1477. ShowMessage("<example> sex testname Male\n");
  1478. ladmin_log("Incomplete parameters to change the sex of an account ('sex' command).\n");
  1479. return 136;
  1480. }
  1481. if (verify_accountname(name) == 0) {
  1482. return 102;
  1483. }
  1484. sex[0] = TOUPPER(sex[0]);
  1485. if (strchr("MF", sex[0]) == NULL) {
  1486. ShowMessage("Illegal gender [%s]. Please input M or F.\n", sex);
  1487. ladmin_log("Illegal gender [%s]. Please input M or F.\n", sex);
  1488. return 103;
  1489. }
  1490. ladmin_log("Request to login-server to change a sex.\n");
  1491. WFIFOW(login_fd,0) = 0x793c;
  1492. memcpy(WFIFOP(login_fd,2), name, 24);
  1493. WFIFOB(login_fd,26) = sex[0];
  1494. WFIFOSET(login_fd,27);
  1495. bytes_to_read = 1;
  1496. return 0;
  1497. }
  1498. //-------------------------------------------------------------------------
  1499. // Sub-function of sub-function changestate, blockaccount or unblockaccount
  1500. // Asking to modify the state of an account
  1501. //-------------------------------------------------------------------------
  1502. int changestatesub(char* name, int state, char* error_message7)
  1503. {
  1504. char error_message[1023]; // need to use, because we can modify error_message7
  1505. WFIFOHEAD(login_fd,50);
  1506. memset(error_message, '\0', sizeof(error_message));
  1507. strncpy(error_message, error_message7, sizeof(error_message)-1);
  1508. if ((state < 0 || state > 9) && state != 100) { // Valid values: 0: ok, or value of the 0x006a packet + 1
  1509. ShowMessage("Please input one of these states:\n");
  1510. ShowMessage(" 0 = Account ok 6 = Your Game's EXE file is not the latest version\n");
  1511. ShowMessage(" 1 = Unregistered ID 7 = You are Prohibited to log in until + message\n");
  1512. ShowMessage(" 2 = Incorrect Password 8 = Server is jammed due to over populated\n");
  1513. ShowMessage(" 3 = This ID is expired 9 = No MSG\n");
  1514. ShowMessage(" 4 = Rejected from Server 100 = This ID has been totally erased\n");
  1515. ShowMessage(" 5 = You have been blocked by the GM Team\n");
  1516. ShowMessage("<examples> state testname 5\n");
  1517. ShowMessage(" state testname 7 end of your ban\n");
  1518. ShowMessage(" block <account name>\n");
  1519. ShowMessage(" unblock <account name>\n");
  1520. ladmin_log("Invalid value for the state of an account ('state', 'block' or 'unblock' command).\n");
  1521. return 151;
  1522. }
  1523. if (verify_accountname(name) == 0) {
  1524. return 102;
  1525. }
  1526. if (state != 7) {
  1527. strcpy(error_message, "-");
  1528. } else {
  1529. if (strlen(error_message) < 1) {
  1530. ShowMessage("Error message is too short. Please input a message of 1-19 bytes.\n");
  1531. ladmin_log("Error message is too short. Please input a message of 1-19 bytes.\n");
  1532. return 102;
  1533. }
  1534. if (strlen(error_message) > 19) {
  1535. ShowMessage("Error message is too long. Please input a message of 1-19 bytes.\n");
  1536. ladmin_log("Error message is too long. Please input a message of 1-19 bytes.\n");
  1537. return 102;
  1538. }
  1539. }
  1540. ladmin_log("Request to login-server to change a state.\n");
  1541. WFIFOW(login_fd,0) = 0x7936;
  1542. memcpy(WFIFOP(login_fd,2), name, 24);
  1543. WFIFOL(login_fd,26) = state;
  1544. memcpy(WFIFOP(login_fd,30), error_message, 20);
  1545. WFIFOSET(login_fd,50);
  1546. bytes_to_read = 1;
  1547. return 0;
  1548. }
  1549. //-------------------------------------------------------
  1550. // Sub-function: Asking to modify the state of an account
  1551. //-------------------------------------------------------
  1552. int changestate(char* param)
  1553. {
  1554. char name[1023], error_message[1023];
  1555. int state;
  1556. memset(name, '\0', sizeof(name));
  1557. memset(error_message, '\0', sizeof(error_message));
  1558. if (sscanf(param, "\"%[^\"]\" %d %[^\r\n]", name, &state, error_message) < 2 &&
  1559. sscanf(param, "'%[^']' %d %[^\r\n]", name, &state, error_message) < 2 &&
  1560. sscanf(param, "%s %d %[^\r\n]", name, &state, error_message) < 2) {
  1561. ShowMessage("Please input an account name and a state.\n");
  1562. ShowMessage("<examples> state testname 5\n");
  1563. ShowMessage(" state testname 7 end of your ban\n");
  1564. ShowMessage(" block <account name>\n");
  1565. ShowMessage(" unblock <account name>\n");
  1566. ladmin_log("Incomplete parameters to change the state of an account ('state' command).\n");
  1567. return 136;
  1568. }
  1569. return changestatesub(name, state, error_message);
  1570. }
  1571. //-------------------------------------------
  1572. // Sub-function: Asking to unblock an account
  1573. //-------------------------------------------
  1574. int unblockaccount(char* param)
  1575. {
  1576. char name[1023];
  1577. memset(name, '\0', sizeof(name));
  1578. if (strlen(param) == 0 ||
  1579. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1580. sscanf(param, "'%[^']'", name) < 1 &&
  1581. sscanf(param, "%[^\r\n]", name) < 1) ||
  1582. strlen(name) == 0)
  1583. {
  1584. ShowMessage("Please input an account name.\n");
  1585. ShowMessage("<examples> state testname 5\n");
  1586. ShowMessage(" state testname 7 end of your ban\n");
  1587. ShowMessage(" block <account name>\n");
  1588. ShowMessage(" unblock <account name>\n");
  1589. ladmin_log("Incomplete parameters to change the state of an account ('unblock' command).\n");
  1590. return 136;
  1591. }
  1592. return changestatesub(name, 0, "-"); // state 0, no error message
  1593. }
  1594. //-------------------------------------------
  1595. // Sub-function: Asking to unblock an account
  1596. //-------------------------------------------
  1597. int blockaccount(char* param)
  1598. {
  1599. char name[1023];
  1600. memset(name, '\0', sizeof(name));
  1601. if (strlen(param) == 0 ||
  1602. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1603. sscanf(param, "'%[^']'", name) < 1 &&
  1604. sscanf(param, "%[^\r\n]", name) < 1) ||
  1605. strlen(name) == 0)
  1606. {
  1607. ShowMessage("Please input an account name.\n");
  1608. ShowMessage("<examples> state testname 5\n");
  1609. ShowMessage(" state testname 7 end of your ban\n");
  1610. ShowMessage(" block <account name>\n");
  1611. ShowMessage(" unblock <account name>\n");
  1612. ladmin_log("Incomplete parameters to change the state of an account ('block' command).\n");
  1613. return 136;
  1614. }
  1615. return changestatesub(name, 5, "-"); // state 5, no error message
  1616. }
  1617. //---------------------------------------------------------------------
  1618. // Sub-function: Add/substract time to the validity limit of an account
  1619. //---------------------------------------------------------------------
  1620. int timeaddaccount(char* param)
  1621. {
  1622. char name[1023], modif[1023];
  1623. int year, month, day, hour, minute, second;
  1624. char * p_modif;
  1625. int value, i;
  1626. WFIFOHEAD(login_fd,38);
  1627. memset(name, '\0', sizeof(name));
  1628. memset(modif, '\0', sizeof(modif));
  1629. year = month = day = hour = minute = second = 0;
  1630. if (sscanf(param, "\"%[^\"]\" %[^\r\n]", name, modif) < 2 &&
  1631. sscanf(param, "'%[^']' %[^\r\n]", name, modif) < 2 &&
  1632. sscanf(param, "%s %[^\r\n]", name, modif) < 2)
  1633. {
  1634. ShowMessage("Please input an account name and a modifier.\n");
  1635. ShowMessage(" <example>: timeadd testname +1m-2mn1s-6y\n");
  1636. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  1637. ShowMessage(" and 6 years at the same time.\n");
  1638. ladmin_log("Incomplete parameters to modify a limit time ('timeadd' command).\n");
  1639. return 136;
  1640. }
  1641. if (verify_accountname(name) == 0) {
  1642. return 102;
  1643. }
  1644. // lowercase for modif
  1645. for (i = 0; modif[i]; i++)
  1646. modif[i] = TOLOWER(modif[i]);
  1647. p_modif = modif;
  1648. while (strlen(p_modif) > 0) {
  1649. value = atoi(p_modif);
  1650. if (value == 0) {
  1651. p_modif++;
  1652. } else {
  1653. if (p_modif[0] == '-' || p_modif[0] == '+')
  1654. p_modif++;
  1655. while (strlen(p_modif) > 0 && p_modif[0] >= '0' && p_modif[0] <= '9') {
  1656. p_modif++;
  1657. }
  1658. if (p_modif[0] == 's') {
  1659. second = value;
  1660. p_modif++;
  1661. } else if (p_modif[0] == 'm' && p_modif[1] == 'n') {
  1662. minute = value;
  1663. p_modif += 2;
  1664. } else if (p_modif[0] == 'h') {
  1665. hour = value;
  1666. p_modif++;
  1667. } else if (p_modif[0] == 'd' || p_modif[0] == 'j') {
  1668. day = value;
  1669. p_modif += 2;
  1670. } else if (p_modif[0] == 'm') {
  1671. month = value;
  1672. p_modif++;
  1673. } else if (p_modif[0] == 'y' || p_modif[0] == 'a') {
  1674. year = value;
  1675. p_modif++;
  1676. } else {
  1677. p_modif++;
  1678. }
  1679. }
  1680. }
  1681. ShowMessage(" year: %d\n", year);
  1682. ShowMessage(" month: %d\n", month);
  1683. ShowMessage(" day: %d\n", day);
  1684. ShowMessage(" hour: %d\n", hour);
  1685. ShowMessage(" minute: %d\n", minute);
  1686. ShowMessage(" second: %d\n", second);
  1687. if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) {
  1688. ShowMessage("Please give an adjustment with this command:\n");
  1689. ShowMessage(" Adjustment value (-1, 1, +1, etc...)\n");
  1690. ShowMessage(" Modified element:\n");
  1691. ShowMessage(" a or y: year\n");
  1692. ShowMessage(" m: month\n");
  1693. ShowMessage(" j or d: day\n");
  1694. ShowMessage(" h: hour\n");
  1695. ShowMessage(" mn: minute\n");
  1696. ShowMessage(" s: second\n");
  1697. ShowMessage(" <example> timeadd testname +1m-2mn1s-6y\n");
  1698. ShowMessage(" this example adds 1 month and 1 second, and substracts 2 minutes\n");
  1699. ShowMessage(" and 6 years at the same time.\n");
  1700. ladmin_log("No adjustment isn't an adjustment ('timeadd' command).\n");
  1701. return 137;
  1702. }
  1703. if (year > 127 || year < -127) {
  1704. ShowMessage("Please give a correct adjustment for the years (from -127 to 127).\n");
  1705. ladmin_log("Abnormal adjustment for the year ('timeadd' command).\n");
  1706. return 137;
  1707. }
  1708. if (month > 255 || month < -255) {
  1709. ShowMessage("Please give a correct adjustment for the months (from -255 to 255).\n");
  1710. ladmin_log("Abnormal adjustment for the month ('timeadd' command).\n");
  1711. return 137;
  1712. }
  1713. if (day > 32767 || day < -32767) {
  1714. ShowMessage("Please give a correct adjustment for the days (from -32767 to 32767).\n");
  1715. ladmin_log("Abnormal adjustment for the days ('timeadd' command).\n");
  1716. return 137;
  1717. }
  1718. if (hour > 32767 || hour < -32767) {
  1719. ShowMessage("Please give a correct adjustment for the hours (from -32767 to 32767).\n");
  1720. ladmin_log("Abnormal adjustment for the hours ('timeadd' command).\n");
  1721. return 137;
  1722. }
  1723. if (minute > 32767 || minute < -32767) {
  1724. ShowMessage("Please give a correct adjustment for the minutes (from -32767 to 32767).\n");
  1725. ladmin_log("Abnormal adjustment for the minutes ('timeadd' command).\n");
  1726. return 137;
  1727. }
  1728. if (second > 32767 || second < -32767) {
  1729. ShowMessage("Please give a correct adjustment for the seconds (from -32767 to 32767).\n");
  1730. ladmin_log("Abnormal adjustment for the seconds ('timeadd' command).\n");
  1731. return 137;
  1732. }
  1733. ladmin_log("Request to login-server to modify a time limit.\n");
  1734. WFIFOW(login_fd,0) = 0x7950;
  1735. memcpy(WFIFOP(login_fd,2), name, 24);
  1736. WFIFOW(login_fd,26) = (short)year;
  1737. WFIFOW(login_fd,28) = (short)month;
  1738. WFIFOW(login_fd,30) = (short)day;
  1739. WFIFOW(login_fd,32) = (short)hour;
  1740. WFIFOW(login_fd,34) = (short)minute;
  1741. WFIFOW(login_fd,36) = (short)second;
  1742. WFIFOSET(login_fd,38);
  1743. bytes_to_read = 1;
  1744. return 0;
  1745. }
  1746. //-------------------------------------------------
  1747. // Sub-function: Set a validity limit of an account
  1748. //-------------------------------------------------
  1749. int timesetaccount(char* param)
  1750. {
  1751. char name[1023], date[1023], time[1023];
  1752. int year, month, day, hour, minute, second;
  1753. time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  1754. struct tm *tmtime;
  1755. WFIFOHEAD(login_fd,30);
  1756. memset(name, '\0', sizeof(name));
  1757. memset(date, '\0', sizeof(date));
  1758. memset(time, '\0', sizeof(time));
  1759. year = month = day = hour = minute = second = 0;
  1760. expiration_time = 0;
  1761. tmtime = localtime(&expiration_time); // initialize
  1762. if (sscanf(param, "\"%[^\"]\" %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
  1763. sscanf(param, "'%[^']' %s %[^\r\n]", name, date, time) < 2 && // if date = 0, time can be void
  1764. sscanf(param, "%s %s %[^\r\n]", name, date, time) < 2) { // if date = 0, time can be void
  1765. ShowMessage("Please input an account name, a date and a hour.\n");
  1766. ShowMessage("<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n");
  1767. ShowMessage(" timeset <account_name> 0 (0 = unlimited)\n");
  1768. ShowMessage(" Default time [hh:mm:ss]: 23:59:59.\n");
  1769. ladmin_log("Incomplete parameters to set a limit time ('timeset' command).\n");
  1770. return 136;
  1771. }
  1772. if (verify_accountname(name) == 0) {
  1773. return 102;
  1774. }
  1775. if (time[0] == '\0')
  1776. strcpy(time, "23:59:59");
  1777. if (atoi(date) != 0 &&
  1778. ((sscanf(date, "%d/%d/%d", &year, &month, &day) < 3 &&
  1779. sscanf(date, "%d-%d-%d", &year, &month, &day) < 3 &&
  1780. sscanf(date, "%d.%d.%d", &year, &month, &day) < 3 &&
  1781. sscanf(date, "%d'%d'%d", &year, &month, &day) < 3) ||
  1782. sscanf(time, "%d:%d:%d", &hour, &minute, &second) < 3))
  1783. {
  1784. ShowMessage("Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
  1785. ladmin_log("Invalid format for the date/time ('timeset' command).\n");
  1786. return 102;
  1787. }
  1788. if (atoi(date) == 0) {
  1789. expiration_time = 0;
  1790. } else {
  1791. if (year < 70) {
  1792. year = year + 100;
  1793. }
  1794. if (year >= 1900) {
  1795. year = year - 1900;
  1796. }
  1797. if (month < 1 || month > 12) {
  1798. ShowMessage("Please give a correct value for the month (from 1 to 12).\n");
  1799. ladmin_log("Invalid month for the date ('timeset' command).\n");
  1800. return 102;
  1801. }
  1802. month = month - 1;
  1803. if (day < 1 || day > 31) {
  1804. ShowMessage("Please give a correct value for the day (from 1 to 31).\n");
  1805. ladmin_log("Invalid day for the date ('timeset' command).\n");
  1806. return 102;
  1807. }
  1808. if (((month == 3 || month == 5 || month == 8 || month == 10) && day > 30) ||
  1809. (month == 1 && day > 29)) {
  1810. ShowMessage("Please give a correct value for a day of this month (%d).\n", month);
  1811. ladmin_log("Invalid day for this month ('timeset' command).\n");
  1812. return 102;
  1813. }
  1814. if (hour < 0 || hour > 23) {
  1815. ShowMessage("Please give a correct value for the hour (from 0 to 23).\n");
  1816. ladmin_log("Invalid hour for the time ('timeset' command).\n");
  1817. return 102;
  1818. }
  1819. if (minute < 0 || minute > 59) {
  1820. ShowMessage("Please give a correct value for the minutes (from 0 to 59).\n");
  1821. ladmin_log("Invalid minute for the time ('timeset' command).\n");
  1822. return 102;
  1823. }
  1824. if (second < 0 || second > 59) {
  1825. ShowMessage("Please give a correct value for the seconds (from 0 to 59).\n");
  1826. ladmin_log("Invalid second for the time ('timeset' command).\n");
  1827. return 102;
  1828. }
  1829. tmtime->tm_year = year;
  1830. tmtime->tm_mon = month;
  1831. tmtime->tm_mday = day;
  1832. tmtime->tm_hour = hour;
  1833. tmtime->tm_min = minute;
  1834. tmtime->tm_sec = second;
  1835. tmtime->tm_isdst = -1; // -1: no winter/summer time modification
  1836. expiration_time = mktime(tmtime);
  1837. if (expiration_time == -1) {
  1838. ShowMessage("Invalid date.\n");
  1839. ShowMessage("Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n");
  1840. ladmin_log("Invalid date. ('timeset' command).\n");
  1841. return 102;
  1842. }
  1843. }
  1844. ladmin_log("Request to login-server to set a time limit.\n");
  1845. WFIFOW(login_fd,0) = 0x7948;
  1846. memcpy(WFIFOP(login_fd,2), name, 24);
  1847. WFIFOL(login_fd,26) = (int)expiration_time;
  1848. WFIFOSET(login_fd,30);
  1849. bytes_to_read = 1;
  1850. return 0;
  1851. }
  1852. //------------------------------------------------------------------------------
  1853. // Sub-function: Asking to displaying information about an account (by its name)
  1854. //------------------------------------------------------------------------------
  1855. int whoaccount(char* param)
  1856. {
  1857. char name[1023];
  1858. WFIFOHEAD(login_fd,26);
  1859. memset(name, '\0', sizeof(name));
  1860. if (strlen(param) == 0 ||
  1861. (sscanf(param, "\"%[^\"]\"", name) < 1 &&
  1862. sscanf(param, "'%[^']'", name) < 1 &&
  1863. sscanf(param, "%[^\r\n]", name) < 1) ||
  1864. strlen(name) == 0)
  1865. {
  1866. ShowMessage("Please input an account name.\n");
  1867. ShowMessage("<example> who testname\n");
  1868. ladmin_log("No name was given to found the account.\n");
  1869. return 136;
  1870. }
  1871. if (verify_accountname(name) == 0) {
  1872. return 102;
  1873. }
  1874. ladmin_log("Request to login-server to obtain information about an account (by its name).\n");
  1875. WFIFOW(login_fd,0) = 0x7952;
  1876. memcpy(WFIFOP(login_fd,2), name, 24);
  1877. WFIFOSET(login_fd,26);
  1878. bytes_to_read = 1;
  1879. return 0;
  1880. }
  1881. //--------------------------------------------------------
  1882. // Sub-function: Asking of the version of the login-server
  1883. //--------------------------------------------------------
  1884. int checkloginversion(void)
  1885. {
  1886. WFIFOHEAD(login_fd,2);
  1887. ladmin_log("Request to login-server to obtain its version.\n");
  1888. WFIFOW(login_fd,0) = 0x7530;
  1889. WFIFOSET(login_fd,2);
  1890. bytes_to_read = 1;
  1891. return 0;
  1892. }
  1893. //---------------------------------------------
  1894. // Prompt function
  1895. // this function wait until user type a command
  1896. // and analyse the command.
  1897. //---------------------------------------------
  1898. int prompt(void)
  1899. {
  1900. int i, j;
  1901. char buf[1024];
  1902. char *p;
  1903. // while we don't wait new packets
  1904. while (bytes_to_read == 0) {
  1905. // for help with the console colors look here:
  1906. // http://www.edoceo.com/liberum/?doc=printf-with-color
  1907. // some code explanation (used here):
  1908. // \033[2J : clear screen and go up/left (0, 0 position)
  1909. // \033[K : clear line from actual position to end of the line
  1910. // \033[0m : reset color parameter
  1911. // \033[1m : use bold for font
  1912. ShowMessage("\n");
  1913. ShowMessage("\033[32mTo list the commands, type 'enter'.\033[0m\n");
  1914. ShowMessage("\033[0;36mLadmin-> \033[0m");
  1915. ShowMessage("\033[1m");
  1916. fflush(stdout);
  1917. // get command and parameter
  1918. memset(buf, '\0', sizeof(buf));
  1919. fflush(stdin);
  1920. fgets(buf, sizeof(buf), stdin);
  1921. ShowMessage("\033[0m");
  1922. fflush(stdout);
  1923. // remove final \n
  1924. if((p = strrchr(buf, '\n')) != NULL)
  1925. p[0] = '\0';
  1926. // remove all control char
  1927. for (i = 0; buf[i]; i++)
  1928. if (buf[i] < 32) {
  1929. // remove cursor control.
  1930. if (buf[i] == 27 && buf[i+1] == '[' &&
  1931. (buf[i+2] == 'H' || // home position (cursor)
  1932. buf[i+2] == 'J' || // clear screen
  1933. buf[i+2] == 'A' || // up 1 line
  1934. buf[i+2] == 'B' || // down 1 line
  1935. buf[i+2] == 'C' || // right 1 position
  1936. buf[i+2] == 'D' || // left 1 position
  1937. buf[i+2] == 'G')) { // center cursor (windows)
  1938. for (j = i; buf[j]; j++)
  1939. buf[j] = buf[j+3];
  1940. } else if (buf[i] == 27 && buf[i+1] == '[' && buf[i+2] == '2' && buf[i+3] == 'J') { // clear screen
  1941. for (j = i; buf[j]; j++)
  1942. buf[j] = buf[j+4];
  1943. } else if (buf[i] == 27 && buf[i+1] == '[' && buf[i+3] == '~' &&
  1944. (buf[i+2] == '1' || // home (windows)
  1945. buf[i+2] == '2' || // insert (windows)
  1946. buf[i+2] == '3' || // del (windows)
  1947. buf[i+2] == '4' || // end (windows)
  1948. buf[i+2] == '5' || // pgup (windows)
  1949. buf[i+2] == '6')) { // pgdown (windows)
  1950. for (j = i; buf[j]; j++)
  1951. buf[j] = buf[j+4];
  1952. } else {
  1953. // remove other control char.
  1954. for (j = i; buf[j]; j++)
  1955. buf[j] = buf[j+1];
  1956. }
  1957. i--;
  1958. }
  1959. // extract command name and parameters
  1960. memset(command, '\0', sizeof(command));
  1961. memset(parameters, '\0', sizeof(parameters));
  1962. sscanf(buf, "%1023s %[^\n]", command, parameters);
  1963. command[1023] = '\0';
  1964. parameters[1023] = '\0';
  1965. // lowercase for command line
  1966. for (i = 0; command[i]; i++)
  1967. command[i] = TOLOWER(command[i]);
  1968. if (command[0] == '?' || strlen(command) == 0) {
  1969. strcpy(buf, "help");
  1970. strcpy(command, "help");
  1971. }
  1972. // Analyse of the command
  1973. check_command(command); // give complete name to the command
  1974. if (strlen(parameters) == 0) {
  1975. ladmin_log("Command: '%s' (without parameters)\n", command, parameters);
  1976. } else {
  1977. ladmin_log("Command: '%s', parameters: '%s'\n", command, parameters);
  1978. }
  1979. // Analyse of the command
  1980. // help
  1981. if (strcmp(command, "help") == 0 ) {
  1982. display_help(parameters);
  1983. // general commands
  1984. } else if (strcmp(command, "add") == 0) {
  1985. addaccount(parameters, 0); // 0: no email
  1986. } else if (strcmp(command, "ban") == 0) {
  1987. banaccount(parameters);
  1988. } else if (strcmp(command, "banadd") == 0) {
  1989. banaddaccount(parameters);
  1990. } else if (strcmp(command, "banset") == 0) {
  1991. bansetaccount(parameters);
  1992. } else if (strcmp(command, "block") == 0) {
  1993. blockaccount(parameters);
  1994. } else if (strcmp(command, "check") == 0) {
  1995. checkaccount(parameters);
  1996. } else if (strcmp(command, "create") == 0) {
  1997. addaccount(parameters, 1); // 1: with email
  1998. } else if (strcmp(command, "delete") == 0) {
  1999. delaccount(parameters);
  2000. } else if (strcmp(command, "email") == 0) {
  2001. changeemail(parameters);
  2002. } else if (strcmp(command, "getcount") == 0) {
  2003. getlogincount();
  2004. } else if (strcmp(command, "gm") == 0) {
  2005. changegmlevel(parameters);
  2006. } else if (strcmp(command, "id") == 0) {
  2007. idaccount(parameters);
  2008. } else if (strcmp(command, "info") == 0) {
  2009. infoaccount(atoi(parameters));
  2010. } else if (strcmp(command, "kami") == 0) {
  2011. sendbroadcast(0, parameters); // flag for normal
  2012. } else if (strcmp(command, "kamib") == 0) {
  2013. sendbroadcast(0x10, parameters); // flag for blue
  2014. } else if (strcmp(command, "list") == 0) {
  2015. listaccount(parameters, 0); // 0: to list all
  2016. } else if (strcmp(command, "listban") == 0) {
  2017. listaccount(parameters, 3); // 3: to list only accounts with state or bannished
  2018. } else if (strcmp(command, "listgm") == 0) {
  2019. listaccount(parameters, 1); // 1: to list only GM
  2020. } else if (strcmp(command, "listok") == 0) {
  2021. listaccount(parameters, 4); // 4: to list only accounts without state and not bannished
  2022. } else if (strcmp(command, "memo") == 0) {
  2023. changememo(parameters);
  2024. } else if (strcmp(command, "name") == 0) {
  2025. nameaccount(atoi(parameters));
  2026. } else if (strcmp(command, "password") == 0) {
  2027. changepasswd(parameters);
  2028. } else if (strcmp(command, "reloadgm") == 0) {
  2029. reloadGM();
  2030. } else if (strcmp(command, "search") == 0) { // no regex in C version
  2031. listaccount(parameters, 2); // 2: to list with pattern
  2032. } else if (strcmp(command, "sex") == 0) {
  2033. changesex(parameters);
  2034. } else if (strcmp(command, "state") == 0) {
  2035. changestate(parameters);
  2036. } else if (strcmp(command, "timeadd") == 0) {
  2037. timeaddaccount(parameters);
  2038. } else if (strcmp(command, "timeset") == 0) {
  2039. timesetaccount(parameters);
  2040. } else if (strcmp(command, "unban") == 0) {
  2041. unbanaccount(parameters);
  2042. } else if (strcmp(command, "unblock") == 0) {
  2043. unblockaccount(parameters);
  2044. } else if (strcmp(command, "version") == 0) {
  2045. checkloginversion();
  2046. } else if (strcmp(command, "who") == 0) {
  2047. whoaccount(parameters);
  2048. // quit
  2049. } else if (strcmp(command, "quit") == 0 ||
  2050. strcmp(command, "exit") == 0 ||
  2051. strcmp(command, "end") == 0) {
  2052. ShowMessage("Bye.\n");
  2053. exit(EXIT_SUCCESS);
  2054. // unknown command
  2055. } else {
  2056. ShowMessage("Unknown command [%s].\n", buf);
  2057. ladmin_log("Unknown command [%s].\n", buf);
  2058. }
  2059. }
  2060. return 0;
  2061. }
  2062. //-------------------------------------------------------------
  2063. // Function: Parse receiving informations from the login-server
  2064. //-------------------------------------------------------------
  2065. int parse_fromlogin(int fd)
  2066. {
  2067. struct char_session_data *sd;
  2068. int id;
  2069. RFIFOHEAD(fd);
  2070. if (session[fd]->flag.eof) {
  2071. ShowMessage("Impossible to have a connection with the login-server [%s:%d] !\n", loginserverip, loginserverport);
  2072. ladmin_log("Impossible to have a connection with the login-server [%s:%d] !\n", loginserverip, loginserverport);
  2073. do_close(fd);
  2074. exit(EXIT_FAILURE);
  2075. }
  2076. // ShowMessage("parse_fromlogin : %d %d %d\n", fd, RFIFOREST(fd), RFIFOW(fd,0));
  2077. sd = (struct char_session_data*)session[fd]->session_data;
  2078. while(RFIFOREST(fd) >= 2) {
  2079. switch(RFIFOW(fd,0)) {
  2080. case 0x7919: // answer of a connection request
  2081. if (RFIFOREST(fd) < 3)
  2082. return 0;
  2083. if (RFIFOB(fd,2) != 0) {
  2084. ShowMessage("Error at login:\n");
  2085. ShowMessage(" - incorrect password,\n");
  2086. ShowMessage(" - administration system not activated, or\n");
  2087. ShowMessage(" - unauthorised IP.\n");
  2088. ladmin_log("Error at login: incorrect password, administration system not activated, or unauthorised IP.\n");
  2089. set_eof(fd);
  2090. //bytes_to_read = 1; // not stop at prompt
  2091. return 0;
  2092. } else {
  2093. ShowMessage("Established connection.\n");
  2094. ladmin_log("Established connection.\n");
  2095. ShowMessage("Reading of the version of the login-server...\n");
  2096. ladmin_log("Reading of the version of the login-server...\n");
  2097. //bytes_to_read = 1; // unchanged
  2098. checkloginversion();
  2099. }
  2100. RFIFOSKIP(fd,3);
  2101. break;
  2102. case 0x01dc: // answer of a coding key request
  2103. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  2104. return 0;
  2105. {
  2106. char md5str[64] = "", md5bin[32];
  2107. WFIFOHEAD(login_fd, 20);
  2108. if (passenc == 1) {
  2109. strncpy(md5str, (const char*)RFIFOP(fd,4), RFIFOW(fd,2) - 4);
  2110. strcat(md5str, loginserveradminpassword);
  2111. } else if (passenc == 2) {
  2112. strncpy(md5str, loginserveradminpassword, sizeof(loginserveradminpassword));
  2113. strcat(md5str, (const char*)RFIFOP(fd,4));
  2114. }
  2115. MD5_Binary(md5str, md5bin);
  2116. WFIFOW(login_fd,0) = 0x7918; // Request for administation login (encrypted password)
  2117. WFIFOW(login_fd,2) = passenc; // Encrypted type
  2118. memcpy(WFIFOP(login_fd,4), md5bin, 16);
  2119. WFIFOSET(login_fd,20);
  2120. ShowMessage("Receiving of the MD5 key.\n");
  2121. ladmin_log("Receiving of the MD5 key.\n");
  2122. ShowMessage("Sending of the encrypted password...\n");
  2123. ladmin_log("Sending of the encrypted password...\n");
  2124. }
  2125. bytes_to_read = 1;
  2126. RFIFOSKIP(fd,RFIFOW(fd,2));
  2127. break;
  2128. case 0x7531: // Displaying of the version of the login-server
  2129. if (RFIFOREST(fd) < 10)
  2130. return 0;
  2131. ShowMessage(" Login-Server [%s:%d]\n", loginserverip, loginserverport);
  2132. if (((int)RFIFOB(login_fd,5)) == 0) {
  2133. ShowMessage(" eAthena version stable-%d.%d", (int)RFIFOB(login_fd,2), (int)RFIFOB(login_fd,3));
  2134. } else {
  2135. ShowMessage(" eAthena version dev-%d.%d", (int)RFIFOB(login_fd,2), (int)RFIFOB(login_fd,3));
  2136. }
  2137. if (((int)RFIFOB(login_fd,4)) == 0)
  2138. ShowMessage(" revision %d", (int)RFIFOB(login_fd,4));
  2139. if (((int)RFIFOB(login_fd,6)) == 0)
  2140. ShowMessage("%d.\n", RFIFOW(login_fd,8));
  2141. else
  2142. ShowMessage("-mod%d.\n", RFIFOW(login_fd,8));
  2143. bytes_to_read = 0;
  2144. RFIFOSKIP(fd,10);
  2145. break;
  2146. case 0x7921: // Displaying of the list of accounts
  2147. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  2148. return 0;
  2149. if (RFIFOW(fd,2) < 5) {
  2150. ladmin_log(" Receiving of a void accounts list.\n");
  2151. if (list_count == 0)
  2152. ShowMessage("No account found.\n");
  2153. else if (list_count == 1)
  2154. ShowMessage("1 account found.\n");
  2155. else
  2156. ShowMessage("%d accounts found.\n", list_count);
  2157. bytes_to_read = 0;
  2158. } else {
  2159. int i;
  2160. WFIFOHEAD(login_fd,10);
  2161. ladmin_log(" Receiving of a accounts list.\n");
  2162. for(i = 4; i < RFIFOW(fd,2); i += 38) {
  2163. int j;
  2164. char userid[24];
  2165. char lower_userid[24];
  2166. memcpy(userid, RFIFOP(fd,i + 5), sizeof(userid));
  2167. userid[sizeof(userid)-1] = '\0';
  2168. memset(lower_userid, '\0', sizeof(lower_userid));
  2169. for (j = 0; userid[j]; j++)
  2170. lower_userid[j] = TOLOWER(userid[j]);
  2171. list_first = RFIFOL(fd,i) + 1;
  2172. // here are checks...
  2173. if (list_type == 0 ||
  2174. (list_type == 1 && RFIFOB(fd,i+4) > 0) ||
  2175. (list_type == 2 && strstr(lower_userid, parameters) != NULL) ||
  2176. (list_type == 3 && RFIFOL(fd,i+34) != 0) ||
  2177. (list_type == 4 && RFIFOL(fd,i+34) == 0)) {
  2178. ShowMessage("%10d ", (int)RFIFOL(fd,i));
  2179. if (RFIFOB(fd,i+4) == 0)
  2180. ShowMessage(" ");
  2181. else
  2182. ShowMessage("%2d ", (int)RFIFOB(fd,i+4));
  2183. ShowMessage("%-24s", userid);
  2184. if (RFIFOB(fd,i+29) == 0)
  2185. ShowMessage("%-5s ", "Femal");
  2186. else if (RFIFOB(fd,i+29) == 1)
  2187. ShowMessage("%-5s ", "Male");
  2188. else
  2189. ShowMessage("%-5s ", "Servr");
  2190. ShowMessage("%6d ", (int)RFIFOL(fd,i+30));
  2191. switch(RFIFOL(fd,i+34)) {
  2192. case 0:
  2193. ShowMessage("%-27s\n", "Account OK");
  2194. break;
  2195. case 1:
  2196. ShowMessage("%-27s\n", "Unregistered ID");
  2197. break;
  2198. case 2:
  2199. ShowMessage("%-27s\n", "Incorrect Password");
  2200. break;
  2201. case 3:
  2202. ShowMessage("%-27s\n", "This ID is expired");
  2203. break;
  2204. case 4:
  2205. ShowMessage("%-27s\n", "Rejected from Server");
  2206. break;
  2207. case 5:
  2208. ShowMessage("%-27s\n", "Blocked by the GM Team"); // You have been blocked by the GM Team
  2209. break;
  2210. case 6:
  2211. ShowMessage("%-27s\n", "Your EXE file is too old"); // Your Game's EXE file is not the latest version
  2212. break;
  2213. case 7:
  2214. ShowMessage("%-27s\n", "Banishement or");
  2215. ShowMessage(" Prohibited to login until...\n"); // You are Prohibited to log in until %s
  2216. break;
  2217. case 8:
  2218. ShowMessage("%-27s\n", "Server is over populated");
  2219. break;
  2220. case 9:
  2221. ShowMessage("%-27s\n", "No MSG");
  2222. break;
  2223. default: // 100
  2224. ShowMessage("%-27s\n", "This ID is totally erased"); // This ID has been totally erased
  2225. break;
  2226. }
  2227. list_count++;
  2228. }
  2229. }
  2230. // asking of the following acounts
  2231. ladmin_log("Request to login-server to obtain the list of accounts from %d to %d (complement).\n", list_first, list_last);
  2232. WFIFOW(login_fd,0) = 0x7920;
  2233. WFIFOL(login_fd,2) = list_first;
  2234. WFIFOL(login_fd,6) = list_last;
  2235. WFIFOSET(login_fd,10);
  2236. bytes_to_read = 1;
  2237. }
  2238. RFIFOSKIP(fd,RFIFOW(fd,2));
  2239. break;
  2240. case 0x7931: // Answer of login-server about an account creation
  2241. if (RFIFOREST(fd) < 30)
  2242. return 0;
  2243. id = RFIFOL(fd,2);
  2244. if (id != -1) {
  2245. ShowMessage("Account [%s] creation failed. Return code %d.\n", RFIFOP(fd,6), id);
  2246. ladmin_log("Account [%s] creation failed. Return code %d.\n", RFIFOP(fd,6), id);
  2247. } else {
  2248. ShowMessage("Account [%s] is successfully created.\n", RFIFOP(fd,6));
  2249. ladmin_log("Account [%s] is successfully created.\n", RFIFOP(fd,6));
  2250. }
  2251. bytes_to_read = 0;
  2252. RFIFOSKIP(fd,30);
  2253. break;
  2254. case 0x7933: // Answer of login-server about an account deletion
  2255. if (RFIFOREST(fd) < 30)
  2256. return 0;
  2257. if (RFIFOL(fd,2) == -1) {
  2258. ShowMessage("Account [%s] deletion failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2259. ladmin_log("Account [%s] deletion failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2260. } else {
  2261. ShowMessage("Account [%s][id: %d] is successfully DELETED.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
  2262. ladmin_log("Account [%s][id: %d] is successfully DELETED.\n", RFIFOP(fd,6), RFIFOL(fd,2));
  2263. }
  2264. bytes_to_read = 0;
  2265. RFIFOSKIP(fd,30);
  2266. break;
  2267. case 0x7935: // answer of the change of an account password
  2268. if (RFIFOREST(fd) < 30)
  2269. return 0;
  2270. if (RFIFOL(fd,2) == -1) {
  2271. ShowMessage("Account [%s] password changing failed.\n", RFIFOP(fd,6));
  2272. ShowMessage("Account [%s] doesn't exist.\n", RFIFOP(fd,6));
  2273. ladmin_log("Account password changing failed. The compte [%s] doesn't exist.\n", RFIFOP(fd,6));
  2274. } else {
  2275. ShowMessage("Account [%s][id: %d] password successfully changed.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
  2276. ladmin_log("Account [%s][id: %d] password successfully changed.\n", RFIFOP(fd,6), (int)RFIFOL(fd,2));
  2277. }
  2278. bytes_to_read = 0;
  2279. RFIFOSKIP(fd,30);
  2280. break;
  2281. case 0x7937: // answer of the change of an account state
  2282. if (RFIFOREST(fd) < 34)
  2283. return 0;
  2284. if (RFIFOL(fd,2) == -1) {
  2285. ShowMessage("Account [%s] state changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2286. ladmin_log("Account [%s] state changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2287. } else {
  2288. char tmpstr[256];
  2289. sprintf(tmpstr, "Account [%s] state successfully changed in [", RFIFOP(fd,6));
  2290. switch(RFIFOL(fd,30)) {
  2291. case 0:
  2292. strcat(tmpstr, "0: Account OK");
  2293. case 1:
  2294. strcat(tmpstr, "1: Unregistered ID");
  2295. break;
  2296. case 2:
  2297. strcat(tmpstr, "2: Incorrect Password");
  2298. break;
  2299. case 3:
  2300. strcat(tmpstr, "3: This ID is expired");
  2301. break;
  2302. case 4:
  2303. strcat(tmpstr, "4: Rejected from Server");
  2304. break;
  2305. case 5:
  2306. strcat(tmpstr, "5: You have been blocked by the GM Team");
  2307. break;
  2308. case 6:
  2309. strcat(tmpstr, "6: [Your Game's EXE file is not the latest version");
  2310. break;
  2311. case 7:
  2312. strcat(tmpstr, "7: You are Prohibited to log in until...");
  2313. break;
  2314. case 8:
  2315. strcat(tmpstr, "8: Server is jammed due to over populated");
  2316. break;
  2317. case 9:
  2318. strcat(tmpstr, "9: No MSG");
  2319. break;
  2320. default: // 100
  2321. strcat(tmpstr, "100: This ID is totally erased");
  2322. break;
  2323. }
  2324. strcat(tmpstr, "]");
  2325. ShowMessage("%s\n", tmpstr);
  2326. ladmin_log("%s\n", tmpstr);
  2327. }
  2328. bytes_to_read = 0;
  2329. RFIFOSKIP(fd,34);
  2330. break;
  2331. case 0x7939: // answer of the number of online players
  2332. if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
  2333. return 0;
  2334. {
  2335. // Get length of the received packet
  2336. int i;
  2337. char name[20];
  2338. ladmin_log(" Receiving of the number of online players.\n");
  2339. // Read information of the servers
  2340. if (RFIFOW(fd,2) < 5) {
  2341. ShowMessage(" No server is connected to the login-server.\n");
  2342. } else {
  2343. ShowMessage(" Number of online players (server: number).\n");
  2344. // Displaying of result
  2345. for(i = 4; i < RFIFOW(fd,2); i += 32) {
  2346. memcpy(name, RFIFOP(fd,i+6), sizeof(name));
  2347. name[sizeof(name) - 1] = '\0';
  2348. ShowMessage(" %-20s : %5d\n", name, RFIFOW(fd,i+26));
  2349. }
  2350. }
  2351. }
  2352. bytes_to_read = 0;
  2353. RFIFOSKIP(fd,RFIFOW(fd,2));
  2354. break;
  2355. case 0x793b: // answer of the check of a password
  2356. if (RFIFOREST(fd) < 30)
  2357. return 0;
  2358. id = RFIFOL(fd,2);
  2359. if (id == -1) {
  2360. ShowMessage("The account [%s] doesn't exist or the password is incorrect.\n", RFIFOP(fd,6));
  2361. ladmin_log("The account [%s] doesn't exist or the password is incorrect.\n", RFIFOP(fd,6));
  2362. } else {
  2363. ShowMessage("The proposed password is correct for the account [%s][id: %d].\n", RFIFOP(fd,6), id);
  2364. ladmin_log("The proposed password is correct for the account [%s][id: %d].\n", RFIFOP(fd,6), id);
  2365. }
  2366. bytes_to_read = 0;
  2367. RFIFOSKIP(fd,30);
  2368. break;
  2369. case 0x793d: // answer of the change of an account sex
  2370. if (RFIFOREST(fd) < 30)
  2371. return 0;
  2372. id = RFIFOL(fd,2);
  2373. if (id == -1) {
  2374. ShowMessage("Account [%s] sex changing failed.\n", RFIFOP(fd,6));
  2375. ShowMessage("Account [%s] doesn't exist or the sex is already the good sex.\n", RFIFOP(fd,6));
  2376. ladmin_log("Account sex changing failed. The compte [%s] doesn't exist or the sex is already the good sex.\n", RFIFOP(fd,6));
  2377. } else {
  2378. ShowMessage("Account [%s][id: %d] sex successfully changed.\n", RFIFOP(fd,6), id);
  2379. ladmin_log("Account [%s][id: %d] sex successfully changed.\n", RFIFOP(fd,6), id);
  2380. }
  2381. bytes_to_read = 0;
  2382. RFIFOSKIP(fd,30);
  2383. break;
  2384. case 0x793f: // answer of the change of an account GM level
  2385. if (RFIFOREST(fd) < 30)
  2386. return 0;
  2387. id = RFIFOL(fd,2);
  2388. if (id == -1) {
  2389. ShowMessage("Account [%s] GM level changing failed.\n", RFIFOP(fd,6));
  2390. ShowMessage("Account [%s] doesn't exist, the GM level is already the good GM level\n", RFIFOP(fd,6));
  2391. ShowMessage("or it's impossible to modify the GM accounts file.\n");
  2392. ladmin_log("Account GM level changing failed. The compte [%s] doesn't exist, the GM level is already the good sex or it's impossible to modify the GM accounts file.\n", RFIFOP(fd,6));
  2393. } else {
  2394. ShowMessage("Account [%s][id: %d] GM level successfully changed.\n", RFIFOP(fd,6), id);
  2395. ladmin_log("Account [%s][id: %d] GM level successfully changed.\n", RFIFOP(fd,6), id);
  2396. }
  2397. bytes_to_read = 0;
  2398. RFIFOSKIP(fd,30);
  2399. break;
  2400. case 0x7941: // answer of the change of an account email
  2401. if (RFIFOREST(fd) < 30)
  2402. return 0;
  2403. id = RFIFOL(fd,2);
  2404. if (id == -1) {
  2405. ShowMessage("Account [%s] e-mail changing failed.\n", RFIFOP(fd,6));
  2406. ShowMessage("Account [%s] doesn't exist.\n", RFIFOP(fd,6));
  2407. ladmin_log("Account e-mail changing failed. The compte [%s] doesn't exist.\n", RFIFOP(fd,6));
  2408. } else {
  2409. ShowMessage("Account [%s][id: %d] e-mail successfully changed.\n", RFIFOP(fd,6), id);
  2410. ladmin_log("Account [%s][id: %d] e-mail successfully changed.\n", RFIFOP(fd,6), id);
  2411. }
  2412. bytes_to_read = 0;
  2413. RFIFOSKIP(fd,30);
  2414. break;
  2415. case 0x7943: // answer of the change of an account memo
  2416. if (RFIFOREST(fd) < 30)
  2417. return 0;
  2418. id = RFIFOL(fd,2);
  2419. if (id == -1) {
  2420. ShowMessage("Account [%s] memo changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2421. ladmin_log("Account [%s] memo changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2422. } else {
  2423. ShowMessage("Account [%s][id: %d] memo successfully changed.\n", RFIFOP(fd,6), id);
  2424. ladmin_log("Account [%s][id: %d] memo successfully changed.\n", RFIFOP(fd,6), id);
  2425. }
  2426. bytes_to_read = 0;
  2427. RFIFOSKIP(fd,30);
  2428. break;
  2429. case 0x7945: // answer of an account id search
  2430. if (RFIFOREST(fd) < 30)
  2431. return 0;
  2432. id = RFIFOL(fd,2);
  2433. if (id == -1) {
  2434. ShowMessage("Unable to find the account [%s] id. Account doesn't exist.\n", RFIFOP(fd,6));
  2435. ladmin_log("Unable to find the account [%s] id. Account doesn't exist.\n", RFIFOP(fd,6));
  2436. } else {
  2437. ShowMessage("The account [%s] have the id: %d.\n", RFIFOP(fd,6), id);
  2438. ladmin_log("The account [%s] have the id: %d.\n", RFIFOP(fd,6), id);
  2439. }
  2440. bytes_to_read = 0;
  2441. RFIFOSKIP(fd,30);
  2442. break;
  2443. case 0x7947: // answer of an account name search
  2444. if (RFIFOREST(fd) < 30)
  2445. return 0;
  2446. id = RFIFOL(fd,2);
  2447. if (strcmp((const char*)RFIFOP(fd,6), "") == 0) {
  2448. ShowMessage("Unable to find the account [%d] name. Account doesn't exist.\n", id);
  2449. ladmin_log("Unable to find the account [%d] name. Account doesn't exist.\n", id);
  2450. } else {
  2451. ShowMessage("The account [id: %d] have the name: %s.\n", id, RFIFOP(fd,6));
  2452. ladmin_log("The account [id: %d] have the name: %s.\n", id, RFIFOP(fd,6));
  2453. }
  2454. bytes_to_read = 0;
  2455. RFIFOSKIP(fd,30);
  2456. break;
  2457. case 0x7949: // answer of an account validity limit set
  2458. if (RFIFOREST(fd) < 34)
  2459. return 0;
  2460. id = RFIFOL(fd,2);
  2461. if (id == -1) {
  2462. ShowMessage("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2463. ladmin_log("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2464. } else {
  2465. time_t timestamp = RFIFOL(fd,30);
  2466. if (timestamp == 0) {
  2467. ShowMessage("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", RFIFOP(fd,6), id);
  2468. ladmin_log("Validity Limit of the account [%s][id: %d] successfully changed to [unlimited].\n", RFIFOP(fd,6), id);
  2469. } else {
  2470. char tmpstr[128];
  2471. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2472. ShowMessage("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2473. ladmin_log("Validity Limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2474. }
  2475. }
  2476. bytes_to_read = 0;
  2477. RFIFOSKIP(fd,34);
  2478. break;
  2479. case 0x794b: // answer of an account ban set
  2480. if (RFIFOREST(fd) < 34)
  2481. return 0;
  2482. id = RFIFOL(fd,2);
  2483. if (id == -1) {
  2484. ShowMessage("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2485. ladmin_log("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2486. } else {
  2487. time_t timestamp = RFIFOL(fd,30);
  2488. if (timestamp == 0) {
  2489. ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
  2490. ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
  2491. } else {
  2492. char tmpstr[128];
  2493. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2494. ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2495. ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2496. }
  2497. }
  2498. bytes_to_read = 0;
  2499. RFIFOSKIP(fd,34);
  2500. break;
  2501. case 0x794d: // answer of an account ban date/time changing
  2502. if (RFIFOREST(fd) < 34)
  2503. return 0;
  2504. id = RFIFOL(fd,2);
  2505. if (id == -1) {
  2506. ShowMessage("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2507. ladmin_log("Account [%s] final date of banishment changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2508. } else {
  2509. time_t timestamp = RFIFOL(fd,30);
  2510. if (timestamp == 0) {
  2511. ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
  2512. ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to [unbanished].\n", RFIFOP(fd,6), id);
  2513. } else {
  2514. char tmpstr[128];
  2515. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2516. ShowMessage("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2517. ladmin_log("Final date of banishment of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2518. }
  2519. }
  2520. bytes_to_read = 0;
  2521. RFIFOSKIP(fd,34);
  2522. break;
  2523. case 0x794f: // answer of a broadcast
  2524. if (RFIFOREST(fd) < 4)
  2525. return 0;
  2526. if (RFIFOW(fd,2) == (unsigned short)-1) {
  2527. ShowMessage("Message sending failed. No online char-server.\n");
  2528. ladmin_log("Message sending failed. No online char-server.\n");
  2529. } else {
  2530. ShowMessage("Message successfully sended to login-server.\n");
  2531. ladmin_log("Message successfully sended to login-server.\n");
  2532. }
  2533. bytes_to_read = 0;
  2534. RFIFOSKIP(fd,4);
  2535. break;
  2536. case 0x7951: // answer of an account validity limit changing
  2537. if (RFIFOREST(fd) < 34)
  2538. return 0;
  2539. id = RFIFOL(fd,2);
  2540. if (id == -1) {
  2541. ShowMessage("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2542. ladmin_log("Account [%s] validity limit changing failed. Account doesn't exist.\n", RFIFOP(fd,6));
  2543. } else {
  2544. time_t timestamp = RFIFOL(fd,30);
  2545. if (timestamp == 0) {
  2546. ShowMessage("Validity limit of the account [%s][id: %d] unchanged.\n", RFIFOP(fd,6), id);
  2547. ShowMessage("The account have an unlimited validity limit or\n");
  2548. ShowMessage("the changing is impossible with the proposed adjustments.\n");
  2549. ladmin_log("Validity limit of the account [%s][id: %d] unchanged. The account have an unlimited validity limit or the changing is impossible with the proposed adjustments.\n", RFIFOP(fd,6), id);
  2550. } else {
  2551. char tmpstr[128];
  2552. strftime(tmpstr, 24, date_format, localtime(&timestamp));
  2553. ShowMessage("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2554. ladmin_log("Validity limit of the account [%s][id: %d] successfully changed to be until %s.\n", RFIFOP(fd,6), id, tmpstr);
  2555. }
  2556. }
  2557. bytes_to_read = 0;
  2558. RFIFOSKIP(fd,34);
  2559. break;
  2560. case 0x7953: // answer of a request about informations of an account (by account name/id)
  2561. if (RFIFOREST(fd) < 150 || RFIFOREST(fd) < (size_t)(150 + RFIFOW(fd,148)))
  2562. return 0;
  2563. {
  2564. char userid[24], error_message[20], lastlogin[24], last_ip[16], email[40], memo[255];
  2565. time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
  2566. time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
  2567. safestrncpy(userid, (char*)RFIFOP(fd,7), sizeof(userid));
  2568. safestrncpy(error_message, (char*)RFIFOP(fd,40), sizeof(error_message));
  2569. safestrncpy(lastlogin, (char*)RFIFOP(fd,60), sizeof(lastlogin));
  2570. safestrncpy(last_ip, (char*)RFIFOP(fd,84), sizeof(last_ip));
  2571. safestrncpy(email, (char*)RFIFOP(fd,100), sizeof(email));
  2572. expiration_time = (time_t)RFIFOL(fd,140);
  2573. unban_time = (time_t)RFIFOL(fd,144);
  2574. memset(memo, '\0', sizeof(memo));
  2575. safestrncpy(memo, (const char*)RFIFOP(fd,150), RFIFOW(fd,148));
  2576. id = RFIFOL(fd,2);
  2577. if (id == -1) {
  2578. ShowMessage("Unabled to find the account [%s]. Account doesn't exist.\n", parameters);
  2579. ladmin_log("Unabled to find the account [%s]. Account doesn't exist.\n", parameters);
  2580. } else if (strlen(userid) == 0) {
  2581. ShowMessage("Unabled to find the account [id: %s]. Account doesn't exist.\n", parameters);
  2582. ladmin_log("Unabled to find the account [id: %s]. Account doesn't exist.\n", parameters);
  2583. } else {
  2584. ladmin_log("Receiving information about an account.\n");
  2585. ShowMessage("The account is set with:\n");
  2586. if (RFIFOB(fd,6) == 0) {
  2587. ShowMessage(" Id: %d (non-GM)\n", id);
  2588. } else {
  2589. ShowMessage(" Id: %d (GM level %d)\n", id, (int)RFIFOB(fd,6));
  2590. }
  2591. ShowMessage(" Name: '%s'\n", userid);
  2592. if (RFIFOB(fd,31) == 0)
  2593. ShowMessage(" Sex: Female\n");
  2594. else if (RFIFOB(fd,31) == 1)
  2595. ShowMessage(" Sex: Male\n");
  2596. else
  2597. ShowMessage(" Sex: Server\n");
  2598. ShowMessage(" E-mail: %s\n", email);
  2599. switch(RFIFOL(fd,36)) {
  2600. case 0: ShowMessage(" State: 0 [Account OK]\n"); break;
  2601. case 1: ShowMessage(" State: 1 [Unregistered ID]\n"); break;
  2602. case 2: ShowMessage(" State: 2 [Incorrect Password]\n"); break;
  2603. case 3: ShowMessage(" State: 3 [This ID is expired]\n"); break;
  2604. case 4: ShowMessage(" State: 4 [Rejected from Server]\n"); break;
  2605. case 5: ShowMessage(" State: 5 [You have been blocked by the GM Team]\n"); break;
  2606. case 6: ShowMessage(" State: 6 [Your Game's EXE file is not the latest version]\n"); break;
  2607. case 7: ShowMessage(" State: 7 [You are Prohibited to log in until %s]\n", error_message); break;
  2608. case 8: ShowMessage(" State: 8 [Server is jammed due to over populated]\n"); break;
  2609. case 9: ShowMessage(" State: 9 [No MSG]\n"); break;
  2610. default: // 100
  2611. ShowMessage(" State: %d [This ID is totally erased]\n", (int)RFIFOL(fd,36));
  2612. break;
  2613. }
  2614. if (unban_time == 0) {
  2615. ShowMessage(" Banishment: not banished.\n");
  2616. } else {
  2617. char tmpstr[128];
  2618. strftime(tmpstr, 24, date_format, localtime(&unban_time));
  2619. ShowMessage(" Banishment: until %s.\n", tmpstr);
  2620. }
  2621. if (RFIFOL(fd,32) > 1)
  2622. ShowMessage(" Count: %d connections.\n", (int)RFIFOL(fd,32));
  2623. else
  2624. ShowMessage(" Count: %d connection.\n", (int)RFIFOL(fd,32));
  2625. ShowMessage(" Last connection at: %s (ip: %s)\n", lastlogin, last_ip);
  2626. if (expiration_time == 0) {
  2627. ShowMessage(" Validity limit: unlimited.\n");
  2628. } else {
  2629. char tmpstr[128];
  2630. strftime(tmpstr, 24, date_format, localtime(&expiration_time));
  2631. ShowMessage(" Validity limit: until %s.\n", tmpstr);
  2632. }
  2633. ShowMessage(" Memo: '%s'\n", memo);
  2634. }
  2635. }
  2636. bytes_to_read = 0;
  2637. RFIFOSKIP(fd,150 + RFIFOW(fd,148));
  2638. break;
  2639. default:
  2640. ShowMessage("Remote administration has been disconnected (unknown packet).\n");
  2641. ladmin_log("'End of connection, unknown packet.\n");
  2642. set_eof(fd);
  2643. return 0;
  2644. }
  2645. }
  2646. // if we don't wait new packets, do the prompt
  2647. prompt();
  2648. return 0;
  2649. }
  2650. //------------------------------------
  2651. // Function to connect to login-server
  2652. //------------------------------------
  2653. int Connect_login_server(void)
  2654. {
  2655. ShowMessage("Attempt to connect to login-server...\n");
  2656. ladmin_log("Attempt to connect to login-server...\n");
  2657. login_fd = make_connection(login_ip, loginserverport);
  2658. if (login_fd == -1)
  2659. { //Might not be the most elegant way to handle this, but I've never used ladmin so I dunno what else you could do. [Skotlex]
  2660. ShowMessage("Error: Failed to connect to Login Server\n");
  2661. exit(EXIT_FAILURE);
  2662. }
  2663. session[login_fd]->flag.server = 1;
  2664. if (passenc == 0) {
  2665. WFIFOHEAD(login_fd,28);
  2666. WFIFOW(login_fd,0) = 0x7918; // Request for administation login
  2667. WFIFOW(login_fd,2) = 0; // no encrypted
  2668. memcpy(WFIFOP(login_fd,4), loginserveradminpassword, 24);
  2669. WFIFOSET(login_fd,28);
  2670. bytes_to_read = 1;
  2671. ShowMessage("Sending of the password...\n");
  2672. ladmin_log("Sending of the password...\n");
  2673. } else {
  2674. WFIFOHEAD(login_fd,2);
  2675. WFIFOW(login_fd,0) = 0x791a; // Sending request about the coding key
  2676. WFIFOSET(login_fd,2);
  2677. bytes_to_read = 1;
  2678. ShowMessage("Request about the MD5 key...\n");
  2679. ladmin_log("Request about the MD5 key...\n");
  2680. }
  2681. return 0;
  2682. }
  2683. // sends a ping packet to login server (will receive pong 0x2718)
  2684. int ping_login_server(int tid, unsigned int tick, int id, intptr data)
  2685. {
  2686. if (login_fd > 0 && session[login_fd] != NULL)
  2687. {
  2688. WFIFOHEAD(login_fd,2);
  2689. WFIFOW(login_fd,0) = 0x2719;
  2690. WFIFOSET(login_fd,2);
  2691. }
  2692. return 0;
  2693. }
  2694. //-----------------------------------
  2695. // Reading general configuration file
  2696. //-----------------------------------
  2697. int ladmin_config_read(const char *cfgName)
  2698. {
  2699. char line[1024], w1[1024], w2[1024];
  2700. FILE *fp;
  2701. fp = fopen(cfgName, "r");
  2702. if (fp == NULL) {
  2703. ShowMessage("\033[0mConfiguration file (%s) not found.\n", cfgName);
  2704. return 1;
  2705. }
  2706. ShowMessage("\033[0m---Start reading of Ladmin configuration file (%s)\n", cfgName);
  2707. while(fgets(line, sizeof(line), fp))
  2708. {
  2709. if (line[0] == '/' && line[1] == '/')
  2710. continue;
  2711. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  2712. remove_control_chars(w1);
  2713. remove_control_chars(w2);
  2714. if(strcmpi(w1,"login_ip")==0) {
  2715. uint32 ipl = host2ip(w2);
  2716. if (ipl != 0) {
  2717. ip2str(ipl, loginserverip);
  2718. ShowMessage("Login server IP address: %s -> %s\n", w2, loginserverip);
  2719. } else
  2720. memcpy(loginserverip, w2, 16);
  2721. } else if (strcmpi(w1, "login_port") == 0) {
  2722. loginserverport = atoi(w2);
  2723. } else if (strcmpi(w1, "admin_pass") == 0) {
  2724. strncpy(loginserveradminpassword, w2, sizeof(loginserveradminpassword));
  2725. loginserveradminpassword[sizeof(loginserveradminpassword)-1] = '\0';
  2726. } else if (strcmpi(w1, "passenc") == 0) {
  2727. passenc = atoi(w2);
  2728. if (passenc < 0 || passenc > 2)
  2729. passenc = 0;
  2730. } else if (strcmpi(w1, "ladmin_log_filename") == 0) {
  2731. strncpy(ladmin_log_filename, w2, sizeof(ladmin_log_filename));
  2732. ladmin_log_filename[sizeof(ladmin_log_filename)-1] = '\0';
  2733. } else if (strcmpi(w1, "date_format") == 0) {
  2734. strncpy(date_format, w2, sizeof(date_format));
  2735. } else if(strcmpi(w1,"stdout_with_ansisequence") == 0) {
  2736. stdout_with_ansisequence = config_switch(w2);
  2737. } else if (strcmpi(w1, "import") == 0) {
  2738. ladmin_config_read(w2);
  2739. }
  2740. }
  2741. }
  2742. fclose(fp);
  2743. login_ip = str2ip(loginserverip);
  2744. ShowMessage("---End reading of Ladmin configuration file.\n");
  2745. return 0;
  2746. }
  2747. //------------------------------
  2748. // Function called when the server
  2749. // has received a crash signal.
  2750. //------------------------------
  2751. void do_abort(void)
  2752. {
  2753. }
  2754. //--------------------------------------
  2755. // Function called at exit of the server
  2756. //--------------------------------------
  2757. void do_final(void)
  2758. {
  2759. if (already_exit_function == 0) {
  2760. ShowMessage("\033[0m----End of Ladmin (normal end with closing of all files).\n");
  2761. ladmin_log("----End of Ladmin (normal end with closing of all files).\n");
  2762. already_exit_function = 1;
  2763. do_close(login_fd);
  2764. }
  2765. }
  2766. //------------------------
  2767. // Main function of ladmin
  2768. //------------------------
  2769. int do_init(int argc, char **argv)
  2770. {
  2771. int next;
  2772. socket_init();
  2773. // read ladmin configuration
  2774. ladmin_config_read((argc > 1) ? argv[1] : LADMIN_CONF_NAME);
  2775. ladmin_log("");
  2776. ladmin_log("Configuration file readed.\n");
  2777. srand(time(NULL));
  2778. set_defaultparse(parse_fromlogin);
  2779. ShowMessage("EAthena login-server administration tool.\n");
  2780. ShowMessage("(for eAthena version %d.%d.%d.)\n", ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION);
  2781. ladmin_log("Ladmin is ready.\n");
  2782. ShowMessage("Ladmin is \033[1;32mready\033[0m.\n\n");
  2783. Connect_login_server();
  2784. // keep the char-login connection alive
  2785. add_timer_func_list(ping_login_server, "ping_login_server");
  2786. add_timer_interval(gettick() + 1000, ping_login_server, 0, 0, ((int)stall_time-2) * 1000);
  2787. // minimalist core doesn't have sockets parsing,
  2788. // so we have to do this ourselves
  2789. while (runflag) {
  2790. next = do_timer(gettick_nocache());
  2791. do_sockets(next);
  2792. }
  2793. return 0;
  2794. }