Browse Source

Merged the /loginmerge branch (topic:192754)
* the login server storage, ipban and logging systems have been abstracted and now provide a common interface; the rest has been merged into a single login server core (no more login/login_sql duplicity)
* storage systems are now added via compiler options (WITH_SQL / WITH_TXT)
* multiple storage engines can be compiled in at the same time, and the config option account.engine defines which one will be used.
* due to MySQL autoincrement limitations, accounts with id '0' will not be supported; account IDs from this point on should start from '1'.
* login_log() functions now again record IP addresses in dotted format, not as 4-byte integers (undo from r6868).
* removed config options that defined column names in the login table
* removed `memo` and `error message` columns from login db/savefile
* moved `loginlog` table to the logs database
* added sql files upgrade_svn12975.sql and upgrade_svn12975_log.sql
* due to changes to the login table layout, I added an !optional! sql file (upgrade_svn12975_view.sql) that will provide a certain degree of backwards compatibility with existing software; read the instructions inside carefully!
* moved third-party includes/libs to a separate directory
* updated project files / makefiles

Changed the way GM levels are handled
* removed conf/gm_account.txt
* added the gm level column to the txt savefile (after 'email' column)
* gm level information is now transferred along with account data

For open problems see bugreport:1889.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@13000 54d463be-8e91-2dee-dedb-b68131a5f0ec

ultramage 17 years ago
parent
commit
106b44c1e7
100 changed files with 5088 additions and 10904 deletions
  1. 0 0
      3rdparty/mysql/include/config-win.h
  2. 0 0
      3rdparty/mysql/include/m_ctype.h
  3. 0 0
      3rdparty/mysql/include/my_alloc.h
  4. 0 0
      3rdparty/mysql/include/my_dbug.h
  5. 0 0
      3rdparty/mysql/include/my_global.h
  6. 0 0
      3rdparty/mysql/include/my_list.h
  7. 0 0
      3rdparty/mysql/include/my_pthread.h
  8. 0 0
      3rdparty/mysql/include/my_sys.h
  9. 0 0
      3rdparty/mysql/include/mysql.h
  10. 0 0
      3rdparty/mysql/include/mysql_com.h
  11. 0 0
      3rdparty/mysql/include/mysql_time.h
  12. 0 0
      3rdparty/mysql/include/mysql_version.h
  13. 0 0
      3rdparty/mysql/include/raid.h
  14. 0 0
      3rdparty/mysql/include/typelib.h
  15. 0 0
      3rdparty/mysql/lib/libmysql.lib
  16. 0 0
      3rdparty/mysql/mysql-5.0.20
  17. 0 0
      3rdparty/pcre/include/pcre.h
  18. 0 0
      3rdparty/pcre/lib/pcre.lib
  19. 0 0
      3rdparty/pcre/pcre-7.0
  20. 0 0
      3rdparty/zlib/include/zconf.h
  21. 0 0
      3rdparty/zlib/include/zlib.h
  22. 0 0
      3rdparty/zlib/lib/zdll.lib
  23. 0 0
      3rdparty/zlib/zlib-1.2.3
  24. 27 0
      Changelog-Trunk.txt
  25. 2 3
      Makefile.in
  26. 8 0
      conf/Changelog.txt
  27. 0 10
      conf/GM_account.txt
  28. 5 0
      conf/battle/gm.conf
  29. 13 26
      conf/inter_athena.conf
  30. 0 5
      conf/ladmin_athena.conf
  31. 37 18
      conf/login_athena.conf
  32. 36 5
      configure
  33. 2 2
      configure.in
  34. 12 15
      save-tmpl/account.txt
  35. 34 34
      save-tmpl/castle.txt
  36. 12 0
      sql-files/logs.sql
  37. 5 21
      sql-files/main.sql
  38. 24 0
      sql-files/upgrade_svn12975.sql
  39. 20 0
      sql-files/upgrade_svn12975_log.sql
  40. 17 0
      sql-files/upgrade_svn12975_view.sql
  41. 34 131
      src/char/char.c
  42. 0 1
      src/char/char.h
  43. 19 15
      src/char/inter.c
  44. 0 3
      src/char/inter.h
  45. 26 162
      src/char_sql/char.c
  46. 0 8
      src/char_sql/char.h
  47. 20 157
      src/char_sql/inter.c
  48. 0 15
      src/char_sql/inter.h
  49. 1 5
      src/common/mmo.h
  50. 1 1
      src/common/plugins.c
  51. 1 1
      src/common/plugins.h
  52. 51 0
      src/common/sql.c
  53. 3 3
      src/common/utils.c
  54. 275 626
      src/ladmin/ladmin.c
  55. 49 14
      src/login/Makefile.in
  56. 159 0
      src/login/account.h
  57. 578 0
      src/login/account_sql.c
  58. 622 0
      src/login/account_txt.c
  59. 294 312
      src/login/admin.c
  60. 25 0
      src/login/ipban.h
  61. 209 0
      src/login/ipban_sql.c
  62. 50 0
      src/login/ipban_txt.c
  63. 166 885
      src/login/login.c
  64. 15 28
      src/login/login.h
  65. 14 0
      src/login/loginlog.h
  66. 93 0
      src/login/loginlog_sql.c
  67. 74 0
      src/login/loginlog_txt.c
  68. 0 60
      src/login_sql/Makefile.in
  69. 0 1982
      src/login_sql/login.c
  70. 0 94
      src/login_sql/login.h
  71. 2 16
      src/map/atcommand.c
  72. 1 0
      src/map/battle.c
  73. 1 0
      src/map/battle.h
  74. 53 74
      src/map/chrif.c
  75. 0 1
      src/map/chrif.h
  76. 2 42
      src/map/map.c
  77. 0 1
      src/map/map.h
  78. 1 1
      src/map/npc_chat.c
  79. 0 1
      src/map/party.c
  80. 0 2
      src/map/party.h
  81. 4 50
      src/map/pc.c
  82. 2 3
      src/map/pc.h
  83. 2 2
      src/map/trade.c
  84. 0 0
      src/mysql/mysql-5.0.20
  85. 41 164
      src/txt-converter/login-converter.c
  86. 0 0
      src/zlib/zlib-1.2.3
  87. 0 204
      tools/cgi/addaccount.cgi
  88. 0 3793
      tools/ladmin
  89. 270 270
      vcproj-6/char-server_sql.dsp
  90. 246 246
      vcproj-6/char-server_txt.dsp
  91. 238 210
      vcproj-6/login-server_sql.dsp
  92. 230 202
      vcproj-6/login-server_txt.dsp
  93. 434 450
      vcproj-6/map-server_sql.dsp
  94. 430 446
      vcproj-6/map-server_txt.dsp
  95. 10 10
      vcproj-7.1/char-server_sql.vcproj
  96. 6 6
      vcproj-7.1/char-server_txt.vcproj
  97. 31 10
      vcproj-7.1/login-server_sql.vcproj
  98. 27 8
      vcproj-7.1/login-server_txt.vcproj
  99. 12 25
      vcproj-7.1/map-server_sql.vcproj
  100. 12 25
      vcproj-7.1/map-server_txt.vcproj

+ 0 - 0
src/mysql/config-win.h → 3rdparty/mysql/include/config-win.h


+ 0 - 0
src/mysql/m_ctype.h → 3rdparty/mysql/include/m_ctype.h


+ 0 - 0
src/mysql/my_alloc.h → 3rdparty/mysql/include/my_alloc.h


+ 0 - 0
src/mysql/my_dbug.h → 3rdparty/mysql/include/my_dbug.h


+ 0 - 0
src/mysql/my_global.h → 3rdparty/mysql/include/my_global.h


+ 0 - 0
src/mysql/my_list.h → 3rdparty/mysql/include/my_list.h


+ 0 - 0
src/mysql/my_pthread.h → 3rdparty/mysql/include/my_pthread.h


+ 0 - 0
src/mysql/my_sys.h → 3rdparty/mysql/include/my_sys.h


+ 0 - 0
src/mysql/mysql.h → 3rdparty/mysql/include/mysql.h


+ 0 - 0
src/mysql/mysql_com.h → 3rdparty/mysql/include/mysql_com.h


+ 0 - 0
src/mysql/mysql_time.h → 3rdparty/mysql/include/mysql_time.h


+ 0 - 0
src/mysql/mysql_version.h → 3rdparty/mysql/include/mysql_version.h


+ 0 - 0
src/mysql/raid.h → 3rdparty/mysql/include/raid.h


+ 0 - 0
src/mysql/typelib.h → 3rdparty/mysql/include/typelib.h


+ 0 - 0
lib/libmysql.lib → 3rdparty/mysql/lib/libmysql.lib


+ 0 - 0
lib/mysql-5.0.20 → 3rdparty/mysql/mysql-5.0.20


+ 0 - 0
src/map/pcre.h → 3rdparty/pcre/include/pcre.h


+ 0 - 0
lib/pcre.lib → 3rdparty/pcre/lib/pcre.lib


+ 0 - 0
lib/pcre-7.0 → 3rdparty/pcre/pcre-7.0


+ 0 - 0
src/zlib/zconf.h → 3rdparty/zlib/include/zconf.h


+ 0 - 0
src/zlib/zlib.h → 3rdparty/zlib/include/zlib.h


+ 0 - 0
lib/zdll.lib → 3rdparty/zlib/lib/zdll.lib


+ 0 - 0
lib/zlib-1.2.3 → 3rdparty/zlib/zlib-1.2.3


+ 27 - 0
Changelog-Trunk.txt

@@ -3,6 +3,33 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2008/07/27
+	* Changed the way GM levels are handled
+	- removed conf/gm_account.txt
+	- added the gm level column to the txt savefile (after 'email' column)
+	- gm level information is now transferred along with account data
+	* Merged the /loginmerge branch [ultramage]
+	- the login server storage, ipban and logging systems have been abstracted
+	  and now provide a common interface; the rest has been merged into a
+	  single login server core (no more login/login_sql duplicity)
+	- storage systems are now added via compiler options (WITH_SQL / WITH_TXT)
+	- multiple storage engines can be compiled in at the same time,
+	  and the config option account.engine defines which one will be used.
+	- due to MySQL autoincrement limitations, accounts with id '0' will not
+	  be supported; account IDs from this point on should start from '1'.
+	- login_log() functions now again record IP addresses in dotted format,
+	  not as 4-byte integers (undo from r6868).
+	- removed config options that defined column names in the login table
+	- removed `memo` and `error message` columns from login db/savefile
+	- moved `loginlog` table to the logs database
+	- added sql files upgrade_svn12975.sql and upgrade_svn12975_log.sql
+	- due to changes to the login table layout, I added an !optional! sql
+	  file (upgrade_svn12975_view.sql) that will provide a certain degree
+	  of backwards compatibility with existing software;
+	  read the instructions inside carefully!
+	- moved third-party includes/libs to a separate directory
+	- updated project files / makefiles
+
 2008/07/20
 	* Simplified the search in pop_timer_heap and added more debug info to help 
 	  determine the source condition of timer errors. (bugreport:1860)

+ 2 - 3
Makefile.in

@@ -43,10 +43,10 @@ common_sql: $(COMMON_SQL_DEPENDS)
 	@$(MAKE) -C src/common sql
 
 login: common
-	@$(MAKE) -C src/login
+	@$(MAKE) -C src/login txt
 
 login_sql: $(LOGIN_SQL_DEPENDS)
-	@$(MAKE) -C src/login_sql
+	@$(MAKE) -C src/login sql
 
 char: common
 	@$(MAKE) -C src/char
@@ -93,7 +93,6 @@ save:
 clean:
 	@$(MAKE) -C src/common $@
 	@$(MAKE) -C src/login $@
-	@$(MAKE) -C src/login_sql $@
 	@$(MAKE) -C src/char $@
 	@$(MAKE) -C src/char_sql $@
 	@$(MAKE) -C src/map $@

+ 8 - 0
conf/Changelog.txt

@@ -1,5 +1,13 @@
 Date	Added
 
+2008/07/27
+	* Conf file adjustments for the loginmerge branch
+	- added new login and ipban db config options to login_athena.conf
+	- login database options are no longer in inter_athena.conf!
+	- moved setting 'lowest_gm_level' from inter_athena.conf to battle/gm.conf
+	- removed setting 'gm_read_method'
+	- removed options for setting `login` table column names
+	- deleted file GM_account.txt, now the savefile is used for this
 2008/07/23
 	* Increased max. hairstyle number, 23 -> 25 (bugreport:1773) [ultramage]
 2008/07/22

+ 0 - 10
conf/GM_account.txt

@@ -1,10 +0,0 @@
-// eAthena's GM Accounts File (for TXT servers only)
-// Edited by MC Cameri to enable account id ranges
-// Changing this file while login server is running 
-// Usage #1(Standard): <account id> <level>
-// Usage #2(Range): <beginning of range[-:~]end of range> <level>
-// Examples:
-// 2000002 99
-// 2000003-2000005 99
-// 2000003~2000005 99
-// 2000001 30

+ 5 - 0
conf/battle/gm.conf

@@ -30,6 +30,11 @@ atcommand_slave_clone_limit: 25
 // current map server.
 partial_name_scan: yes
 
+// The level at which a player with access is considered a GM. 
+// An account with an access level lower than this is not effected
+// by gm_can_drop_lv (battle_athena.conf). 
+lowest_gm_level: 1
+
 // [GM] Can use all skills? (No or mimimum GM level)
 gm_all_skill: no
 

+ 13 - 26
conf/inter_athena.conf

@@ -1,5 +1,17 @@
 // Athena InterServer configuration.
 
+// Options for both versions
+
+// Log Inter Connections, etc.?
+log_inter: 1
+
+// Inter Log Filename
+inter_log_filename: log/inter.log
+
+// Level range for sharing within a party
+party_share_level: 10
+
+
 // TXT version options only
 
 // Storage flatfile database, used for Karfa storage.
@@ -26,32 +38,14 @@ castle_txt: save/castle.txt
 // Status change flatfile database, for status changes that are saved between sessions.
 scdata_txt: save/scdata.txt
 
-// Options for both versions
-
-// Log Inter Connections, etc.?
-log_inter: 1
-
-// Inter Log Filename
-inter_log_filename: log/inter.log
-
-// Level range for sharing within a party
-party_share_level: 10
 
 // SQL version options only
 
-// GM Reading Method
-// 1 to have Char read GMs, 0 to have Login-controlled GMs
-gm_read_method: 0
-
-// The level at which a player with access is considered a GM. 
-// An account with an access level lower than this is not effected
-// by gm_can_drop_lv (battle_athena.conf). 
-lowest_gm_level: 1
-
 // You can specify the codepage to use in your mySQL tables here.
 // (Note that this feature requires MySQL 4.1+)
 //default_codepage: 
 
+
 // For IPs, ideally under linux, you want to use localhost instead of 127.0.0.1 
 // Under windows, you want to use 127.0.0.1.  If you see a message like
 // "Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)"
@@ -96,16 +90,9 @@ db_server_logindb: ragnarok
 // this is meant for people who KNOW their stuff, and for some reason want to change their
 // database layout. [CLOWNISIUS]
 
-//Column names for the login table.
-login_db_account_id: account_id
-login_db_userid: userid
-login_db_user_pass: user_pass
-login_db_level: level
-
 // ALL MySQL Database Table names
 
 // Login Database Tables
-login_db: login
 loginlog_db: loginlog
 
 // Char Database Tables

+ 0 - 5
conf/ladmin_athena.conf

@@ -15,11 +15,6 @@ admin_pass: admin
 // 2: password+key
 passenc: 2
 
-// Language of ladmin
-// F: Français
-// E: English (default)
-defaultlanguage: E
-
 // Log Filename. All operations done by the software are logged in this file.
 ladmin_log_filename: log/ladmin.log
 

+ 37 - 18
conf/login_athena.conf

@@ -38,13 +38,12 @@ console_silent: 0
 // Whether remote administration is enabled or disabled
 admin_state: no
 
-// Administrative password, used by ladmin (perl software) to connect remotely to server.
-// NOTICE: If you enable remote administration, you should change its value for security
-// NOTE: ladmin only works on TXT login servers.
+// Administrative password, used by ladmin to connect remotely to server.
+// NOTICE: you should change this value for security if you use ladmin.
 admin_pass: admin
 
 // Indicate the IP/host that the server accepts for remote administration.
-admin_allowed_ip: 127.0.0.1
+admin_allowed_host: 127.0.0.1
 
 // Console Commands
 // Allow for console commands to be used on/off
@@ -62,15 +61,8 @@ new_account: yes
 allowed_regs: 1
 time_allowed: 10
 
-// Account flatfile database, stores account information.
-account_filename: save/account.txt
-
-// What account AIDs have GM privs, and what level?
-gm_account_filename: conf/GM_account.txt
-
-// Timer to check if GM_account file has been changed and reload GM account automaticaly
-// (in seconds; default: 15; value: 0 (disabled), or 2 or more)
-gm_account_filename_check_timer: 15
+// Log Filename. All operations received by the server are logged in this file. 
+login_log_filename: log/login.log
 
 // To log the login server?
 // NOTE: The login-sql server needs the login logs to enable dynamic pass failure bans.
@@ -110,11 +102,18 @@ client_version_to_connect: 20
 use_MD5_passwords: no
 
 // Ipban features (SQL only)
-ipban: yes
-dynamic_pass_failure_ban: yes
-dynamic_pass_failure_ban_interval: 5
-dynamic_pass_failure_ban_limit: 7
-dynamic_pass_failure_ban_duration: 5
+ipban.enable: yes
+ipban.sql.db_hostname: 127.0.0.1
+ipban.sql.db_port: 3306
+ipban.sql.db_username: ragnarok
+ipban.sql.db_password: ragnarok
+ipban.sql.db_database: ragnarok
+ipban.sql.ipban_table: ipbanlist
+// Dynamic password failure ipban system
+ipban.dynamic_pass_failure_ban: yes
+ipban.dynamic_pass_failure_ban_interval: 5
+ipban.dynamic_pass_failure_ban_limit: 7
+ipban.dynamic_pass_failure_ban_duration: 5
 
 // Interval (in minutes) to execute a DNS/IP update. Disabled by default.
 // Enable it if your server uses a dynamic IP which changes with time.
@@ -126,4 +125,24 @@ dynamic_pass_failure_ban_duration: 5
 use_dnsbl: no
 dnsbl_servers: dnsbl.deltaanime.net
 
+// Which account engine to use.
+// 'auto' selects the first engine available (txt, sql, then others)
+// (defaults to auto)
+account.engine: auto
+
+// Account data storage configuration
+// TXT
+account.txt.account_db: save/account.txt
+account.txt.case_sensitive: no
+// SQL
+account.sql.db_hostname: 127.0.0.1
+account.sql.db_port: 3306
+account.sql.db_username: ragnarok
+account.sql.db_password: ragnarok
+account.sql.db_database: ragnarok
+account.sql.codepage: 
+account.sql.case_sensitive: no
+account.sql.account_db: login
+account.sql.accreg_db: global_reg_value
+
 import: conf/import/login_conf.txt

+ 36 - 5
configure

@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 12803 .
+# From configure.in Revision: 12731 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61.
 #
@@ -663,6 +663,7 @@ OBJEXT
 CPP
 GREP
 EGREP
+HAVE_OPENRJ_TXT
 MYSQL_CONFIG_HOME
 HAVE_MYSQL
 MYSQL_VERSION
@@ -1259,7 +1260,9 @@ Optional Features:
   --enable-mapregsql      Makes map-wide script variables be saved to SQL
                           instead of TXT files in the sql map-server.
                           (disabled by default)
-  --enable-debug          Compiles in debug mode. (disabled by default)
+  --enable-debug          Compiles extra debug code. (disabled by default)
+  --disable-openrj-txt    Disables the openrj-based account engine in the TXT
+                          login-server (enabled by default)
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1718,7 +1721,7 @@ ac_config_files="$ac_config_files Makefile src/common/Makefile"
 
 ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile src/ladmin/Makefile"
 
-ac_config_files="$ac_config_files src/char_sql/Makefile src/login_sql/Makefile src/txt-converter/Makefile"
+ac_config_files="$ac_config_files src/char_sql/Makefile src/txt-converter/Makefile"
 
 ac_config_files="$ac_config_files src/map/Makefile src/plugins/Makefile src/tool/Makefile"
 
@@ -1807,6 +1810,28 @@ fi
 
 
 
+#
+# OpenRJ account engine in the txt login server
+#
+# Check whether --enable-openrj-txt was given.
+if test "${enable_openrj_txt+set}" = set; then
+  enableval=$enable_openrj_txt;
+		HAVE_OPENRJ_TXT="$enableval"
+		case $enableval in
+			no);;
+			yes);;
+			*) { { echo "$as_me:$LINENO: error: invalid argument --enable-openrj-txt=$enableval... stopping" >&5
+echo "$as_me: error: invalid argument --enable-openrj-txt=$enableval... stopping" >&2;}
+   { (exit 1); exit 1; }; };;
+		esac
+
+else
+  HAVE_OPENRJ_TXT="yes"
+
+fi
+
+
+
 #
 # Enable/disable MySql and optionally specify the path to mysql_config (optional library)
 #
@@ -4530,6 +4555,12 @@ if test "$enable_debug" = "yes" ; then
 fi
 
 
+#
+# OpenRJ account engine in the txt login server
+#
+
+
+
 #
 # zlib library (required)
 #
@@ -6002,7 +6033,6 @@ do
     "src/login/Makefile") CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;;
     "src/ladmin/Makefile") CONFIG_FILES="$CONFIG_FILES src/ladmin/Makefile" ;;
     "src/char_sql/Makefile") CONFIG_FILES="$CONFIG_FILES src/char_sql/Makefile" ;;
-    "src/login_sql/Makefile") CONFIG_FILES="$CONFIG_FILES src/login_sql/Makefile" ;;
     "src/txt-converter/Makefile") CONFIG_FILES="$CONFIG_FILES src/txt-converter/Makefile" ;;
     "src/map/Makefile") CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;;
     "src/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES src/plugins/Makefile" ;;
@@ -6115,6 +6145,7 @@ OBJEXT!$OBJEXT$ac_delim
 CPP!$CPP$ac_delim
 GREP!$GREP$ac_delim
 EGREP!$EGREP$ac_delim
+HAVE_OPENRJ_TXT!$HAVE_OPENRJ_TXT$ac_delim
 MYSQL_CONFIG_HOME!$MYSQL_CONFIG_HOME$ac_delim
 HAVE_MYSQL!$HAVE_MYSQL$ac_delim
 MYSQL_VERSION!$MYSQL_VERSION$ac_delim
@@ -6128,7 +6159,7 @@ LIBOBJS!$LIBOBJS$ac_delim
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 59; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 60; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5

+ 2 - 2
configure.in

@@ -7,7 +7,7 @@ AC_PREREQ([2.59])
 AC_CONFIG_SRCDIR([src/common/cbasetypes.h])
 AC_CONFIG_FILES([Makefile src/common/Makefile])
 AC_CONFIG_FILES([src/char/Makefile src/login/Makefile src/ladmin/Makefile])
-AC_CONFIG_FILES([src/char_sql/Makefile src/login_sql/Makefile src/txt-converter/Makefile])
+AC_CONFIG_FILES([src/char_sql/Makefile src/txt-converter/Makefile])
 AC_CONFIG_FILES([src/map/Makefile src/plugins/Makefile src/tool/Makefile])
 
 
@@ -78,7 +78,7 @@ AC_ARG_ENABLE(
 	[debug],
 	AC_HELP_STRING(
 		[--enable-debug],
-		[Compiles in debug mode. (disabled by default)]
+		[Compiles extra debug code. (disabled by default)]
 	),
 	[
 		enable_debug="$enableval"

+ 12 - 15
save-tmpl/account.txt

@@ -1,19 +1,16 @@
+20080409
 // Accounts file: here are saved all information about the accounts.
-// Structure: ID, account name, password, last login time, sex, # of logins, state, email, error message for state 7, validity time, last (accepted) login ip, memo field, ban timestamp, repeated(register text, register value)
-// Some explanations:
-//   account name    : between 4 to 23 char for a normal account (standard client can't send less than 4 char).
-//   account password: between 4 to 23 char
+// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, repeated(register key, register value)
+// where:
 //   sex             : M or F for normal accounts, S for server accounts
+//   level           : this account's gm level
 //   state           : 0: account is ok, 1 to 256: error code of packet 0x006a + 1
-//   email           : between 3 to 39 char (a@a.com is like no email)
-//   error message   : text for the state 7: 'Your are Prohibited to login until <text>'. Max 19 char
-//   valitidy time   : 0: unlimited account, <other value>: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)
-//   memo field      : max 254 char
-//   ban time        : 0: no ban, <other value>: banned until the date: date calculated by addition of 1/1/1970 + value (number of seconds since the 1/1/1970)
-0	s1	p1	2004-10-25 01:12:04.147	S	2	0	a@a.com	-	0	127.0.0.1	-	0	
-1	s2	p2	-	S	0	0	a@a.com	-	0	-	-	0	
-2	s3	p3	-	S	0	0	a@a.com	-	0	-	-	0	
-3	s4	p4	-	S	0	0	a@a.com	-	0	-	-	0	
-4	s5	p5	-	S	0	0	a@a.com	-	0	-	-	0	
-2000001	Test	Test	-	M	0	0	a@a.com	-	0	-	-	0	
+//   unban time      : 0: no ban, <other value>: banned until the date (unix timestamp)
+//   expiration time : 0: unlimited account, <other value>: account expires on the date (unix timestamp)
+1	s1	p1	S	a@a.com	0	0	0	0	0	-	-	
+2	s2	p2	S	a@a.com	0	0	0	0	0	-	-	
+3	s3	p3	S	a@a.com	0	0	0	0	0	-	-	
+4	s4	p4	S	a@a.com	0	0	0	0	0	-	-	
+5	s5	p5	S	a@a.com	0	0	0	0	0	-	-	
+2000001	Test	Test	M	a@a.com	0	0	0	0	0	-	-	
 2000002	%newid%

+ 34 - 34
save-tmpl/castle.txt

@@ -1,34 +1,34 @@
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+30,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

+ 12 - 0
sql-files/logs.sql

@@ -113,3 +113,15 @@ CREATE TABLE `chatlog` (
   INDEX (`src_accountid`),
   INDEX (`src_charid`)
 ) ENGINE=MyISAM AUTO_INCREMENT=1 ;
+
+#Database: log
+#Table: loginlog
+CREATE TABLE `loginlog` (
+  `time` datetime NOT NULL default '0000-00-00 00:00:00',
+  `ip` varchar(15) NOT NULL default '',
+  `user` varchar(23) NOT NULL default '',
+  `rcode` tinyint(4) NOT NULL default '0',
+  `log` varchar(255) NOT NULL default '',
+  INDEX (`ip`)
+) ENGINE=MyISAM ;
+

+ 5 - 21
sql-files/main.sql

@@ -421,17 +421,15 @@ CREATE TABLE `login` (
   `account_id` int(11) unsigned NOT NULL auto_increment,
   `userid` varchar(23) NOT NULL default '',
   `user_pass` varchar(32) NOT NULL default '',
-  `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00',
   `sex` enum('M','F','S') NOT NULL default 'M',
-  `logincount` mediumint(9) unsigned NOT NULL default '0',
   `email` varchar(39) NOT NULL default '',
   `level` tinyint(3) NOT NULL default '0',
-  `error_message` smallint(11) unsigned NOT NULL default '0',
-  `connect_until` int(11) unsigned NOT NULL default '0',
-  `last_ip` varchar(100) NOT NULL default '',
-  `memo` smallint(11) unsigned NOT NULL default '0',
-  `ban_until` int(11) unsigned NOT NULL default '0',
   `state` int(11) unsigned NOT NULL default '0',
+  `unban_time` int(11) unsigned NOT NULL default '0',
+  `expiration_time` int(11) unsigned NOT NULL default '0',
+  `logincount` mediumint(9) unsigned NOT NULL default '0',
+  `lastlogin` datetime NOT NULL default '0000-00-00 00:00:00',
+  `last_ip` varchar(100) NOT NULL default '',
   PRIMARY KEY  (`account_id`),
   KEY `name` (`userid`)
 ) ENGINE=MyISAM AUTO_INCREMENT=2000000; 
@@ -472,20 +470,6 @@ CREATE TABLE `sc_data` (
   KEY (`char_id`)
 ) ENGINE=MyISAM;
 
---
--- Table structure for table `loginlog`
---
-
-DROP TABLE IF EXISTS `loginlog`;
-CREATE TABLE `loginlog` (
-  `time` datetime NOT NULL default '0000-00-00 00:00:00',
-  `ip` int(10) unsigned NOT NULL default '0',
-  `user` varchar(23) NOT NULL default '',
-  `rcode` tinyint(4) NOT NULL default '0',
-  `log` varchar(255) NOT NULL default '',
-  INDEX (`ip`)
-) ENGINE=MyISAM;
-
 --
 -- Table structure for table `mail`
 --

+ 24 - 0
sql-files/upgrade_svn12975.sql

@@ -0,0 +1,24 @@
+START TRANSACTION;
+
+-- delete columns
+ALTER TABLE `login` DROP `error_message`;
+ALTER TABLE `login` DROP `memo`;
+
+-- rename columns
+ALTER TABLE `login` CHANGE `connect_until` `expiration_time` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0';
+ALTER TABLE `login` CHANGE `ban_until` `unban_time` INT( 11 ) UNSIGNED NOT NULL DEFAULT '0';
+
+-- reorder columns
+ALTER TABLE `login` MODIFY `sex` enum('M','F','S') NOT NULL default 'M' AFTER `user_pass`;
+ALTER TABLE `login` MODIFY `email` varchar(39) NOT NULL default '' AFTER `sex`;
+ALTER TABLE `login` MODIFY `level` tinyint(3) NOT NULL default '0' AFTER `email`;
+ALTER TABLE `login` MODIFY `state` int(11) unsigned NOT NULL default '0' AFTER `level`;
+ALTER TABLE `login` MODIFY `unban_time` int(11) unsigned NOT NULL default '0' AFTER `state`;
+ALTER TABLE `login` MODIFY `expiration_time` int(11) unsigned NOT NULL default '0' AFTER `unban_time`;
+ALTER TABLE `login` MODIFY `logincount` mediumint(9) unsigned NOT NULL default '0' AFTER `expiration_time`;
+
+-- change ip format
+ALTER TABLE `loginlog` CHANGE `ip` `ip` VARCHAR( 15 ) NOT NULL default '';
+UPDATE `loginlog` SET `ip` = inet_ntoa(`ip`);
+
+COMMIT;

+ 20 - 0
sql-files/upgrade_svn12975_log.sql

@@ -0,0 +1,20 @@
+-- NOTE: change `ragnarok` and `log` to whatever your database names are.
+
+START TRANSACTION;
+
+CREATE TABLE `log`.`loginlog` (
+  `time` datetime NOT NULL default '0000-00-00 00:00:00',
+  `ip` varchar( 15 ) NOT NULL ,
+  `user` varchar( 23 ) NOT NULL default '',
+  `rcode` tinyint( 4 ) NOT NULL default '0',
+  `log` varchar( 255 ) NOT NULL default '',
+  KEY `ip` ( `ip` ) 
+) ENGINE = MYISAM;
+
+INSERT INTO `log`.`loginlog` 
+  SELECT * 
+  FROM `ragnarok`.`loginlog` ;
+
+DROP TABLE `ragnarok`.`loginlog` ;
+
+COMMIT;

+ 17 - 0
sql-files/upgrade_svn12975_view.sql

@@ -0,0 +1,17 @@
+-- The statements below will create a 'view' (virtual table) that mimics
+-- the previous `login` table layout. You can use this hack to make your db
+-- compatible with older eathena servers or control panels.
+-- Note: also adjust the account.sql.account_db setting in login_athena.conf.
+-- Note: if your CP does not have a config setting for the `login` table name
+--       you'll have to either modify its code or do some table renaming.
+
+START TRANSACTION;
+
+-- create dummy columns, needed to make the view insertable
+ALTER TABLE `login` ADD `error_message` SMALLINT UNSIGNED NOT NULL;
+ALTER TABLE `login` ADD `memo` SMALLINT UNSIGNED NOT NULL;
+
+-- create the view
+CREATE VIEW `login_view` ( `account_id`, `userid`, `user_pass`, `lastlogin`, `sex`, `logincount`, `email`, `level`, `error_message`, `connect_until`, `last_ip`, `memo`, `ban_until`, `state` ) AS SELECT `account_id`, `userid`, `user_pass`, `lastlogin`, `sex`, `logincount`, `email`, `level`, `error_message`, `expiration_time`, `last_ip`, `memo`, `unban_time`, `state` FROM `login`;
+
+COMMIT;

+ 34 - 131
src/char/char.c

@@ -109,6 +109,7 @@ struct char_session_data {
 	int found_char[MAX_CHARS]; // ids of chars on this account
 	char email[40]; // e-mail (default: a@a.com) by [Yor]
 	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+	int gmlevel;
 };
 
 int char_id_count = START_CHAR_NUM;
@@ -136,9 +137,6 @@ struct fame_list taekwon_fame_list[MAX_FAME_LIST];
 // Initial position (it's possible to set it in conf file)
 struct point start_point = { 0, 53, 111 };
 
-struct gm_account *gm_account = NULL;
-int GM_num = 0;
-
 // online players by [Yor]
 char online_txt_filename[1024] = "online.txt";
 char online_html_filename[1024] = "online.html";
@@ -162,6 +160,7 @@ struct auth_node {
 	uint32 ip;
 	int sex;
 	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+	int gmlevel;
 };
 
 static DBMap* auth_db; // int account_id -> struct auth_node*
@@ -344,20 +343,6 @@ int char_log(char *fmt, ...)
 	return 0;
 }
 
-//----------------------------------------------------------------------
-// Determine if an account (id) is a GM account
-// and returns its level (or 0 if it isn't a GM account or if not found)
-//----------------------------------------------------------------------
-int isGM(int account_id)
-{
-	int i;
-
-	for(i = 0; i < GM_num; i++)
-		if (gm_account[i].account_id == account_id)
-			return gm_account[i].level;
-	return 0;
-}
-
 //Search character data from the aid/cid givem
 struct mmo_charstatus* search_character(int aid, int cid)
 {
@@ -1556,7 +1541,8 @@ void create_online_files(void)
 				// displaying the character name
 				if ((online_display_option & 1) || (online_display_option & 64)) { // without/with 'GM' display
 					strcpy(temp, char_dat[j].status.name);
-					l = isGM(char_dat[j].status.account_id);
+					//l = isGM(char_dat[j].status.account_id);
+					l = 0; //FIXME: how to get the gm level?
 					if (online_display_option & 64) {
 						if (l >= online_gm_display_min_level)
 							fprintf(fp, "%-24s (GM) ", temp);
@@ -1892,7 +1878,7 @@ static int char_delete(struct mmo_charstatus *cs)
 static void char_auth_ok(int fd, struct char_session_data *sd)
 {
 	struct online_char_data* character;
-	if (max_connect_user && count_users() >= max_connect_user && isGM(sd->account_id) < gm_allow_level)
+	if (max_connect_user && count_users() >= max_connect_user && sd->gmlevel < gm_allow_level)
 	{
 		// refuse connection (over populated)
 		WFIFOW(fd,0) = 0x6c;
@@ -1999,7 +1985,7 @@ int parse_fromlogin(int fd)
 
 		// acknowledgement of account authentication request
 		case 0x2713:
-			if (RFIFOREST(fd) < 59)
+			if (RFIFOREST(fd) < 60)
 				return 0;
 		{
 			int account_id = RFIFOL(fd,2);
@@ -2008,6 +1994,7 @@ int parse_fromlogin(int fd)
 			bool result = RFIFOB(fd,14);
 			const char* email = (const char*)RFIFOP(fd,15);
 			time_t expiration_time = (time_t)RFIFOL(fd,55);
+			int gmlevel = RFIFOB(fd,59);
 
 			// find the session with this account id
 			ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) &&
@@ -2021,32 +2008,29 @@ int parse_fromlogin(int fd)
 					WFIFOSET(i,3);
 				} else { // success
 					memcpy(sd->email, email, 40);
-					if (e_mail_check(sd->email) == 0)
-						strncpy(sd->email, "a@a.com", 40); // default e-mail
 					sd->expiration_time = expiration_time;
+					sd->gmlevel = gmlevel;
 					char_auth_ok(i, sd);
 				}
 			}
 		}
-			RFIFOSKIP(fd,59);
+			RFIFOSKIP(fd,60);
 		break;
 
 		// Receiving of an e-mail/time limit from the login-server (answer of a request because a player comes back from map-server to char-server) by [Yor]
 		case 0x2717:
-			if (RFIFOREST(fd) < 50)
+			if (RFIFOREST(fd) < 51)
 				return 0;
-			for(i = 0; i < fd_max; i++) {
-				if (session[i] && (sd = (struct char_session_data*)session[i]->session_data)) {
-					if (sd->account_id == RFIFOL(fd,2)) {
-						memcpy(sd->email, RFIFOP(fd,6), 40);
-						if (e_mail_check(sd->email) == 0)
-							strncpy(sd->email, "a@a.com", 40); // default e-mail
-						sd->expiration_time = (time_t)RFIFOL(fd,46);
-						break;
-					}
-				}
+
+			// find the session with this account id
+			ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->account_id == RFIFOL(fd,2) );
+			if( i < fd_max )
+			{
+				memcpy(sd->email, RFIFOP(fd,6), 40);
+				sd->expiration_time = (time_t)RFIFOL(fd,46);
+				sd->gmlevel = RFIFOB(fd,50);
 			}
-			RFIFOSKIP(fd,50);
+			RFIFOSKIP(fd,51);
 		break;
 
 		// login-server alive packet
@@ -2209,7 +2193,7 @@ int parse_fromlogin(int fd)
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
 				return 0;
 		{	//Receive account_reg2 registry, forward to map servers.
-			unsigned char buf[ACCOUNT_REG2_NUM*(256+32+2)+16];
+			unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)];
 			memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2));
 //			WBUFW(buf,0) = 0x2b11;
 			WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex]
@@ -2284,33 +2268,6 @@ int parse_fromlogin(int fd)
 			RFIFOSKIP(fd,11);
 		break;
 
-		// Receiving GM acounts info from login-server (by [Yor])
-		case 0x2732:
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-		{
-			unsigned char buf[32000]; //FIXME: this will crash
-			if (gm_account != NULL)
-				aFree(gm_account);
-			CREATE(gm_account, struct gm_account, (RFIFOW(fd,2) - 4)/5);
-			GM_num = 0;
-			for (i = 4; i < RFIFOW(fd,2); i = i + 5) {
-				gm_account[GM_num].account_id = RFIFOL(fd,i);
-				gm_account[GM_num].level = (int)RFIFOB(fd,i+4);
-				//printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
-				GM_num++;
-			}
-			ShowStatus("From login-server: receiving information of %d GM accounts.\n", GM_num);
-			char_log("From login-server: receiving information of %d GM accounts.\n", GM_num);
-			// send new gm acccounts level to map-servers
-			memcpy(buf, RFIFOP(fd,0), RFIFOW(fd,2));
-			WBUFW(buf,0) = 0x2b15;
-			mapif_sendall(buf, RFIFOW(fd,2));
-
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-		}
-		break;
-
 		// Login server request to kick a character out. [Skotlex]
 		case 0x2734:
 			if (RFIFOREST(fd) < 6)
@@ -2634,15 +2591,6 @@ int parse_frommap(int fd)
 		switch(RFIFOW(fd,0))
 		{
 
-		case 0x2af7: // request from map-server to reload GM accounts. Transmission to login-server
-			if (login_fd > 0) { // don't send request if no login-server
-				WFIFOHEAD(login_fd,2);
-				WFIFOW(login_fd,0) = 0x2709;
-				WFIFOSET(login_fd,2);
-			}
-			RFIFOSKIP(fd,2);
-		break;
-
 		case 0x2afa: // Receiving map names list from the map-server
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
 				return 0;
@@ -2844,8 +2792,9 @@ int parse_frommap(int fd)
 			    char_dat[i].status.char_id == RFIFOL(fd,14))
 				break;
 			}
+
 			char_data = i < char_num ? &char_dat[i].status : NULL;
-			//Tell the new map server about this player using Kevin's new auth packet. [Skotlex]
+
 			if (map_fd >= 0 && session[map_fd] && char_data) 
 			{	//Send the map server the auth of this player.
 				struct auth_node* node;
@@ -2856,19 +2805,6 @@ int parse_frommap(int fd)
 				char_data->last_point.y = RFIFOW(fd,22);
 				char_data->sex = RFIFOB(fd,30);
 
-#if 0
-				// the map-server must request it [FlavioJS]
-				WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus));
-				WFIFOW(map_fd,0) = 0x2afd;
-				WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
-				WFIFOL(map_fd,4) = RFIFOL(fd,2); //Account ID
-				WFIFOL(map_fd,8) = RFIFOL(fd,6); //Login1
-				WFIFOL(map_fd,16) = RFIFOL(fd,10); //Login2
-				WFIFOL(map_fd,12) = (unsigned long)0; //TODO: expiration_time, how do I figure it out right now?
-				memcpy(WFIFOP(map_fd,20), char_data, sizeof(struct mmo_charstatus));
-				WFIFOSET(map_fd, WFIFOW(map_fd,2));
-#endif
-
 				// create temporary auth entry
 				CREATE(node, struct auth_node, 1);
 				node->account_id = RFIFOL(fd,2);
@@ -2959,9 +2895,9 @@ int parse_frommap(int fd)
 
 				if( login_fd <= 0 )
 					result = 3; // 3-login-server offline
-				else
-				if( acc != -1 && isGM(acc) < isGM(account_id) )
-					result = 2; // 2-gm level too low
+//				else
+//				if( acc != -1 && isGM(acc) < isGM(account_id) )
+//					result = 2; // 2-gm level too low
 				else
 				switch( type ) {
 				case 1: // block
@@ -3168,14 +3104,15 @@ int parse_frommap(int fd)
 			{// auth ok
 				cd->sex = sex;
 
-				WFIFOHEAD(fd,20 + sizeof(struct mmo_charstatus));
+				WFIFOHEAD(fd,24 + sizeof(struct mmo_charstatus));
 				WFIFOW(fd,0) = 0x2afd;
-				WFIFOW(fd,2) = 20 + sizeof(struct mmo_charstatus);
+				WFIFOW(fd,2) = 24 + sizeof(struct mmo_charstatus);
 				WFIFOL(fd,4) = account_id;
-				WFIFOL(fd,8) = login_id1;
-				WFIFOL(fd,12) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
-				WFIFOL(fd,16) = node->login_id2;
-				memcpy(WFIFOP(fd,20), cd, sizeof(struct mmo_charstatus));
+				WFIFOL(fd,8) = node->login_id1;
+				WFIFOL(fd,12) = node->login_id2;
+				WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
+				WFIFOL(fd,20) = node->gmlevel;
+				memcpy(WFIFOP(fd,24), cd, sizeof(struct mmo_charstatus));
 				WFIFOSET(fd, WFIFOW(fd,2));
 
 				// only use the auth once and mark user online
@@ -3309,7 +3246,6 @@ int parse_char(int fd)
 				return 0;
 		{
 			struct auth_node* node;
-			int GM_value;
 
 			int account_id = RFIFOL(fd,2);
 			uint32 login_id1 = RFIFOL(fd,6);
@@ -3325,16 +3261,9 @@ int parse_char(int fd)
 				//TODO: and perhaps send back a reply?
 				break;
 			}
-
-			if( (GM_value = isGM(account_id)) != 0 )
-				ShowInfo("Account Logged On; Account ID: %d (GM level %d).\n", account_id, GM_value);
-			else
-				ShowInfo("Account Logged On; Account ID: %d.\n", account_id);
 			
 			CREATE(session[fd]->session_data, struct char_session_data, 1);
 			sd = (struct char_session_data*)session[fd]->session_data;
-			strncpy(sd->email, "no mail", 40); // put here a mail without '@' to refuse deletion if we don't receive the e-mail
-			sd->expiration_time = 0; // unknown or unlimited (not displaying on map-server)
 			sd->account_id = account_id;
 			sd->login_id1 = login_id1;
 			sd->login_id2 = login_id2;
@@ -3454,7 +3383,6 @@ int parse_char(int fd)
 				cd->last_point.map = j;
 			}
 
-			//Send NEW auth packet [Kevin]
 			//FIXME: is this case even possible? [ultramage]
 			if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL)
 			{
@@ -3474,29 +3402,13 @@ int parse_char(int fd)
 			WFIFOW(fd,0) = 0x71;
 			WFIFOL(fd,2) = cd->char_id;
 			mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6));
-
-			// Advanced subnet check [LuzZza]
-			subnet_map_ip = lan_subnetcheck(ipl);
+			subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza]
 			WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
 			WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
 			WFIFOSET(fd,28);
 
 			ShowInfo("Character selection '%s' (account: %d, slot: %d).\n", cd->name, sd->account_id, ch);
 
-#if 0
-			// The server must request it [FlavioJS]
-			//Send auth ok to map server
-			WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus));
-			WFIFOW(map_fd,0) = 0x2afd;
-			WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
-			WFIFOL(map_fd,4) = sd->account_id;
-			WFIFOL(map_fd,8) = sd->login_id1;
-			WFIFOL(map_fd,16) = sd->login_id2;
-			WFIFOL(map_fd,12) = (unsigned long)sd->expiration_time;
-			memcpy(WFIFOP(map_fd,20), cd, sizeof(struct mmo_charstatus));
-			WFIFOSET(map_fd, WFIFOW(map_fd,2));
-#endif
-
 			// create temporary auth entry
 			CREATE(node, struct auth_node, 1);
 			node->account_id = sd->account_id;
@@ -3505,6 +3417,7 @@ int parse_char(int fd)
 			node->login_id2 = sd->login_id2;
 			node->sex = sd->sex;
 			node->expiration_time = sd->expiration_time;
+			node->gmlevel = sd->gmlevel;
 			node->ip = ipl;
 			idb_put(auth_db, sd->account_id, node);
 		}
@@ -3706,15 +3619,6 @@ int parse_char(int fd)
 				session[fd]->flag.server = 1;
 				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
 				char_mapif_init(fd);
-				// send gm acccounts level to map-servers
-				WFIFOHEAD(fd,4+5*GM_num);
-				WFIFOW(fd,0) = 0x2b15;
-				for(i = 0; i < GM_num; i++) {
-					WFIFOL(fd,4+5*i) = gm_account[i].account_id;
-					WFIFOB(fd,4+5*i+4) = (unsigned char)gm_account[i].level;
-				}
-				WFIFOW(fd,2) = 4+5*GM_num;
-				WFIFOSET(fd,WFIFOW(fd,2));
 			}
 
 			RFIFOSKIP(fd,60);
@@ -4245,7 +4149,6 @@ void do_final(void)
 	online_char_db->destroy(online_char_db, NULL); //dispose the db...
 	auth_db->destroy(auth_db, NULL);
 	
-	if(gm_account) aFree(gm_account);
 	if(char_dat) aFree(char_dat);
 
 	if (login_fd > 0)

+ 0 - 1
src/char/char.h

@@ -6,7 +6,6 @@
 
 #include "../common/mmo.h"
 
-#define START_CHAR_NUM 150000
 #define MAX_MAP_SERVERS 30
 
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000

+ 19 - 15
src/char/inter.c

@@ -650,6 +650,25 @@ int mapif_parse_NameChangeRequest(int fd)
 
 //--------------------------------------------------------
 
+/// Returns the length of the next complete packet to process,
+/// or 0 if no complete packet exists in the queue.
+///
+/// @param length The minimum allowed length, or -1 for dynamic lookup
+int inter_check_length(int fd, int length)
+{
+	if( length == -1 )
+	{// variable-length packet
+		if( RFIFOREST(fd) < 4 )
+			return 0;
+		length = RFIFOW(fd,2);
+	}
+
+	if( (int)RFIFOREST(fd) < length )
+		return 0;
+
+	return length;
+}
+
 // map server からの通信(1パケットのみ解析すること)
 // エラーなら0(false)、処理できたなら1、
 // パケット長が足りなければ2をかえさなければならない
@@ -695,19 +714,4 @@ int inter_parse_frommap(int fd) {
 	return 1;
 }
 
-// RFIFOのパケット長確認
-// 必要パケット長があればパケット長、まだ足りなければ0
-int inter_check_length(int fd, int length) {
-	if (length == -1) {	// 可変パケット長
-		RFIFOHEAD(fd);
-		if (RFIFOREST(fd) < 4)	// パケット長が未着
-			return 0;
-		length = RFIFOW(fd,2);
-	}
-
-	if ((int)RFIFOREST(fd) < length)	// パケットが未着
-		return 0;
-
-	return length;
-}
 #endif //TXT_SQL_CONVERT

+ 0 - 3
src/char/inter.h

@@ -13,14 +13,11 @@ int inter_parse_frommap(int fd);
 int inter_mapif_init(int fd);
 int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason);
 
-int inter_check_length(int fd,int length);
-
 int inter_log(char *fmt,...);
 
 #define inter_cfgName "conf/inter_athena.conf"
 
 extern unsigned int party_share_level;
-extern char inter_log_filename[1024];
 extern char main_chat_nick[16];
 
 //For TXT->SQL conversion

+ 26 - 162
src/char_sql/char.c

@@ -69,12 +69,6 @@ char db_path[1024] = "db";
 
 int db_use_sqldbs;
 
-char login_db[256] = "login";
-char login_db_account_id[32] = "account_id";
-char login_db_level[32] = "level";
-
-int lowest_gm_level = 1;
-
 struct mmo_map_server {
 	int fd;
 	uint32 ip;
@@ -135,6 +129,7 @@ struct char_session_data {
 	int found_char[MAX_CHARS]; // ids of chars on this account
 	char email[40]; // e-mail (default: a@a.com) by [Yor]
 	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+	int gmlevel;
 };
 
 int char_num, char_max;
@@ -164,10 +159,6 @@ unsigned int save_flag = 0;
 // Initial position (it's possible to set it in conf file)
 struct point start_point = { 0, 53, 111 };
 
-bool char_gm_read = false;
-struct gm_account *gm_account = NULL;
-int GM_num = 0;
-
 int console = 0;
 
 //-----------------------------------------------------
@@ -183,6 +174,7 @@ struct auth_node {
 	uint32 ip;
 	int sex;
 	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
+	int gmlevel;
 };
 
 static DBMap* auth_db; // int account_id -> struct auth_node*
@@ -394,53 +386,6 @@ void set_all_offline_sql(void)
 		Sql_ShowDebug(sql_handle);
 }
 
-//----------------------------------------------------------------------
-// Determine if an account (id) is a GM account
-// and returns its level (or 0 if it isn't a GM account or if not found)
-//----------------------------------------------------------------------
-int isGM(int account_id)
-{
-	int i;
-
-	for(i = 0; i < GM_num; i++)
-		if (gm_account[i].account_id == account_id)
-			return gm_account[i].level;
-	return 0;
-}
-
-void read_gm_account(void)
-{
-	if(!char_gm_read)
-		return;
-	
-	if (gm_account != NULL)
-		aFree(gm_account);
-	GM_num = 0;
-
-	if( SQL_ERROR == Sql_Query(lsql_handle, "SELECT `%s`,`%s` FROM `%s` WHERE `%s`>='%d'", login_db_account_id, login_db_level, login_db, login_db_level, lowest_gm_level) )
-		Sql_ShowDebug(lsql_handle);
-
-	if( Sql_NumRows(lsql_handle) > 0 )
-	{
-		char* data;
-
-		CREATE(gm_account, struct gm_account, (size_t)Sql_NumRows(lsql_handle));
-		while( SQL_SUCCESS == Sql_NextRow(lsql_handle) )
-		{
-			// account_id
-			Sql_GetData(lsql_handle, 0, &data, NULL);
-			gm_account[GM_num].account_id = atoi(data);
-			// account_id
-			Sql_GetData(lsql_handle, 1, &data, NULL);
-			gm_account[GM_num].level = atoi(data);
-			++GM_num;
-		}
-	}
-	Sql_FreeResult(lsql_handle);
-
-	mapif_send_gmaccounts();
-}
-
 static void* create_charstatus(DBKey key, va_list args)
 {
 	struct mmo_charstatus *cp;
@@ -1636,7 +1581,7 @@ int char_family(int pl1, int pl2, int pl3)
 static void char_auth_ok(int fd, struct char_session_data *sd)
 {
 	struct online_char_data* character;
-	if (max_connect_user && count_users() >= max_connect_user && isGM(sd->account_id) < gm_allow_level)
+	if (max_connect_user && count_users() >= max_connect_user && sd->gmlevel < gm_allow_level)
 	{
 		// refuse connection (over populated)
 		WFIFOW(fd,0) = 0x6c;
@@ -1742,7 +1687,7 @@ int parse_fromlogin(int fd)
 
 		// acknowledgement of account authentication request
 		case 0x2713:
-			if (RFIFOREST(fd) < 59)
+			if (RFIFOREST(fd) < 60)
 				return 0;
 		{
 			int account_id = RFIFOL(fd,2);
@@ -1751,6 +1696,7 @@ int parse_fromlogin(int fd)
 			bool result = RFIFOB(fd,14);
 			const char* email = (const char*)RFIFOP(fd,15);
 			time_t expiration_time = (time_t)RFIFOL(fd,55);
+			int gmlevel = RFIFOB(fd,59);
 
 			// find the session with this account id
 			ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) &&
@@ -1765,16 +1711,17 @@ int parse_fromlogin(int fd)
 				} else { // success
 					memcpy(sd->email, email, 40);
 					sd->expiration_time = expiration_time;
+					sd->gmlevel = gmlevel;
 					char_auth_ok(i, sd);
 				}
 			}
 		}
-			RFIFOSKIP(fd,59);
+			RFIFOSKIP(fd,60);
 		break;
 
 		// acknowledgement of e-mail/limited time request
 		case 0x2717:
-			if (RFIFOREST(fd) < 50)
+			if (RFIFOREST(fd) < 51)
 				return 0;
 
 			// find the session with this account id
@@ -1783,8 +1730,9 @@ int parse_fromlogin(int fd)
 			{
 				memcpy(sd->email, RFIFOP(fd,6), 40);
 				sd->expiration_time = (time_t)RFIFOL(fd,46);
+				sd->gmlevel = RFIFOB(fd,50);
 			}
-			RFIFOSKIP(fd,50);
+			RFIFOSKIP(fd,51);
 		break;
 
 		// login-server alive packet
@@ -1881,7 +1829,7 @@ int parse_fromlogin(int fd)
 				return 0;
 
 		{	//Receive account_reg2 registry, forward to map servers.
-			unsigned char buf[ACCOUNT_REG2_NUM*(256+32+2)+16];
+			unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)];
 			memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2));
 			WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex]
 			mapif_sendall(buf, WBUFW(buf,2));
@@ -1910,33 +1858,6 @@ int parse_fromlogin(int fd)
 			RFIFOSKIP(fd,11);
 		break;
 
-		// gm account information from login server
-		case 0x2732:
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-
-			if(!char_gm_read) {
-				unsigned char buf[32000]; //FIXME: this will crash
-				if (gm_account != NULL)
-					aFree(gm_account);
-				gm_account = (struct gm_account*)aCalloc(sizeof(struct gm_account) * ((RFIFOW(fd,2) - 4) / 5), 1);
-				GM_num = 0;
-				for (i = 4; i < RFIFOW(fd,2); i = i + 5) {
-					gm_account[GM_num].account_id = RFIFOL(fd,i);
-					gm_account[GM_num].level = (int)RFIFOB(fd,i+4);
-					//printf("GM account: %d -> level %d\n", gm_account[GM_num].account_id, gm_account[GM_num].level);
-					GM_num++;
-				}
-				ShowStatus("From login-server: receiving information of %d GM accounts.\n", GM_num);
-				// send new gm acccounts level to map-servers
-				memcpy(buf, RFIFOP(fd,0), RFIFOW(fd,2));
-				WBUFW(buf,0) = 0x2b15;
-				mapif_sendall(buf, RFIFOW(fd,2));
-			}
-
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-		break;
-
 		// Login server request to kick a character out. [Skotlex]
 		case 0x2734:
 			if (RFIFOREST(fd) < 6)
@@ -2214,18 +2135,6 @@ int parse_frommap(int fd)
 		switch(RFIFOW(fd, 0))
 		{
 
-		case 0x2af7: // request from map-server to reload GM accounts. Transmission to login-server
-			if(char_gm_read) //Re-read gm accounts.
-				read_gm_account();
-			//Send to login request to reload gm accounts.
-			else if (login_fd > 0) { // don't send request if no login-server
-				WFIFOHEAD(login_fd,2);
-				WFIFOW(login_fd,0) = 0x2709;
-				WFIFOSET(login_fd,2);
-			}
-			RFIFOSKIP(fd,2);
-		break;
-
 		case 0x2afa: // Receiving map names list from the map-server
 			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
 				return 0;
@@ -2434,7 +2343,8 @@ int parse_frommap(int fd)
 			node->login_id2 = login_id2;
 			//node->sex = 0;
 			node->ip = ntohl(ip);
-			node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
+			//node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server)
+			//node->gmlevel = 0;
 			idb_put(auth_db, account_id, node);
 
 			//Set char to "@ char select" in online db [Kevin]
@@ -2467,7 +2377,7 @@ int parse_frommap(int fd)
 				mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
 				char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
 			}
-			//Tell the new map server about this player using Kevin's new auth packet. [Skotlex]
+
 			if (map_fd >= 0 && session[map_fd] && char_data) 
 			{	//Send the map server the auth of this player.
 				struct auth_node* node;
@@ -2478,19 +2388,6 @@ int parse_frommap(int fd)
 				char_data->last_point.y = RFIFOW(fd,22);
 				char_data->sex = RFIFOB(fd,30);
 
-#if 0
-				// the map-server must request it [FlavioJS]
-				WFIFOHEAD(map_fd, 20 + sizeof(struct mmo_charstatus));
-				WFIFOW(map_fd,0) = 0x2afd;
-				WFIFOW(map_fd,2) = 20 + sizeof(struct mmo_charstatus);
-				WFIFOL(map_fd,4) = RFIFOL(fd,2); //Account ID
-				WFIFOL(map_fd,8) = RFIFOL(fd,6); //Login1
-				WFIFOL(map_fd,16) = RFIFOL(fd,10); //Login2
-				WFIFOL(map_fd,12) = (unsigned long)0; //TODO: expiration_time, how do I figure it out right now?
-				memcpy(WFIFOP(map_fd,20), char_data, sizeof(struct mmo_charstatus));
-				WFIFOSET(map_fd, WFIFOW(map_fd,2));
-#endif
-
 				// create temporary auth entry
 				CREATE(node, struct auth_node, 1);
 				node->account_id = RFIFOL(fd,2);
@@ -2588,9 +2485,10 @@ int parse_frommap(int fd)
 
 				if( login_fd <= 0 )
 					result = 3; // 3-login-server offline
-				else
-				if( acc != -1 && isGM(acc) < isGM(account_id) )
-					result = 2; // 2-gm level too low
+				//FIXME: need to move this check to login server [ultramage]
+//				else
+//				if( acc != -1 && isGM(acc) < isGM(account_id) )
+//					result = 2; // 2-gm level too low
 				else
 				switch( type ) {
 				case 1: // block
@@ -2838,14 +2736,15 @@ int parse_frommap(int fd)
 			{// auth ok
 				cd->sex = sex;
 
-				WFIFOHEAD(fd,20 + sizeof(struct mmo_charstatus));
+				WFIFOHEAD(fd,24 + sizeof(struct mmo_charstatus));
 				WFIFOW(fd,0) = 0x2afd;
-				WFIFOW(fd,2) = 20 + sizeof(struct mmo_charstatus);
+				WFIFOW(fd,2) = 24 + sizeof(struct mmo_charstatus);
 				WFIFOL(fd,4) = account_id;
-				WFIFOL(fd,8) = login_id1;
-				WFIFOL(fd,12) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
-				WFIFOL(fd,16) = node->login_id2;
-				memcpy(WFIFOP(fd,20), cd, sizeof(struct mmo_charstatus));
+				WFIFOL(fd,8) = node->login_id1;
+				WFIFOL(fd,12) = node->login_id2;
+				WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT"
+				WFIFOL(fd,20) = node->gmlevel;
+				memcpy(WFIFOP(fd,24), cd, sizeof(struct mmo_charstatus));
 				WFIFOSET(fd, WFIFOW(fd,2));
 
 				// only use the auth once and mark user online
@@ -2996,7 +2895,6 @@ int parse_char(int fd)
 			
 			CREATE(session[fd]->session_data, struct char_session_data, 1);
 			sd = (struct char_session_data*)session[fd]->session_data;
-			sd->expiration_time = 0; // unknown or unlimited (not displaying on map-server)
 			sd->account_id = account_id;
 			sd->login_id1 = login_id1;
 			sd->login_id2 = login_id2;
@@ -3149,8 +3047,6 @@ int parse_char(int fd)
 			WFIFOW(fd,0) = 0x71;
 			WFIFOL(fd,2) = cp->char_id;
 			mapindex_getmapname_ext(mapindex_id2name(cp->last_point.map), (char*)WFIFOP(fd,6));
-
-			// Advanced subnet check [LuzZza]
 			subnet_map_ip = lan_subnetcheck(ipl);
 			WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip);
 			WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
@@ -3164,6 +3060,7 @@ int parse_char(int fd)
 			node->login_id2 = sd->login_id2;
 			node->sex = sd->sex;
 			node->expiration_time = sd->expiration_time;
+			node->gmlevel = sd->gmlevel;
 			node->ip = ipl;
 			idb_put(auth_db, sd->account_id, node);
 
@@ -3324,15 +3221,6 @@ int parse_char(int fd)
 				session[fd]->flag.server = 1;
 				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
 				char_mapif_init(fd);
-				// send gm acccounts level to map-servers
-				WFIFOHEAD(fd,4+5*GM_num); 
-				WFIFOW(fd,0) = 0x2b15;
-				for(i = 0; i < GM_num; i++) {
-					WFIFOL(fd,4+5*i) = gm_account[i].account_id;
-					WFIFOB(fd,4+5*i+4) = (unsigned char)gm_account[i].level;
-				}
-				WFIFOW(fd,2) = 4+5*GM_num;
-				WFIFOSET(fd,WFIFOW(fd,2));
 			}
 			
 			RFIFOSKIP(fd,60);
@@ -3669,21 +3557,6 @@ void sql_config_read(const char* cfgName)
 
 		if(!strcmpi(w1,"char_db"))
 			strcpy(char_db,w2);
-#ifndef TXT_SQL_CONVERT
-		else if(!strcmpi(w1,"gm_read_method"))
-			char_gm_read = config_switch(w2);
-		//custom columns for login database
-		else if(!strcmpi(w1,"login_db"))
-			strcpy(login_db,w2);
-		else if(!strcmpi(w1,"login_db_level"))
-			strcpy(login_db_level,w2);
-		else if(!strcmpi(w1,"login_db_account_id"))
-			strcpy(login_db_account_id,w2);
-		else if(!strcmpi(w1,"lowest_gm_level")) {
-			lowest_gm_level = atoi(w2);
-			ShowStatus("set lowest_gm_level : %s\n", w2);
-		}
-#endif
 		else if(!strcmpi(w1,"scdata_db"))
 			strcpy(scdata_db,w2);
 		else if(!strcmpi(w1,"cart_db"))
@@ -3920,11 +3793,6 @@ void do_final(void)
 	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo") )
 		Sql_ShowDebug(sql_handle);
 
-	if(gm_account)  {
-		aFree(gm_account);
-		gm_account = 0;
-	}
-
 	if (login_fd > 0)
 		do_close(login_fd);
 	if (char_fd > 0)
@@ -3934,8 +3802,6 @@ void do_final(void)
 	auth_db->destroy(auth_db, NULL);
 
 	Sql_Free(sql_handle);
-	if( lsql_handle )
-		Sql_Free(lsql_handle);
 
 	ShowInfo("ok! all done...\n");
 }
@@ -3986,8 +3852,6 @@ int do_init(int argc, char **argv)
 	online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	mmo_char_sql_init();
 	char_read_fame_list(); //Read fame lists.
-	if(char_gm_read)
-		read_gm_account();
 	ShowInfo("char server initialized.\n");
 
 	set_defaultparse(parse_char);

+ 0 - 8
src/char_sql/char.h

@@ -6,7 +6,6 @@
 
 struct mmo_charstatus;
 
-#define START_CHAR_NUM 150000
 #define MAX_MAP_SERVERS 30
 
 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000
@@ -64,13 +63,6 @@ extern char quest_obj_db[256];
 
 extern int db_use_sqldbs; // added for sql item_db read for char server [Valaris]
 
-extern char login_db_level[32];
-extern char login_db_account_id[32];
-
-extern int lowest_gm_level;
-extern int GM_num;
-extern struct gm_account *gm_account;
-
 extern int guild_exp_rate;
 extern int log_inter;
 

+ 20 - 157
src/char_sql/inter.c

@@ -28,7 +28,6 @@
 
 
 Sql* sql_handle = NULL;
-Sql* lsql_handle = NULL;
 
 int char_server_port = 3306;
 char char_server_ip[32] = "127.0.0.1";
@@ -37,12 +36,6 @@ char char_server_pw[32] = "ragnarok";
 char char_server_db[32] = "ragnarok";
 char default_codepage[32] = ""; //Feature by irmin.
 
-int login_server_port = 3306;
-char login_server_ip[32] = "127.0.0.1";
-char login_server_id[32] = "ragnarok";
-char login_server_pw[32] = "ragnarok";
-char login_server_db[32] = "ragnarok";
-
 #ifndef TXT_SQL_CONVERT
 
 static struct accreg *accreg_pt;
@@ -71,8 +64,6 @@ struct WisData {
 static DBMap* wis_db = NULL; // int wis_id -> struct WisData*
 static int wis_dellist[WISDELLIST_MAX], wis_delnum;
 
-int inter_sql_test (void);
-
 #endif //TXT_SQL_CONVERT
 //--------------------------------------------------------
 // Save registry to sql
@@ -237,29 +228,6 @@ static int inter_config_read(const char* cfgName)
 			strcpy(default_codepage,w2);
 			ShowStatus ("set default_codepage : %s\n", w2);
 		}
-		//Logins information to be read from the inter_athena.conf
-		//for character deletion (checks email in the loginDB)
-		else
-		if(!strcmpi(w1,"login_server_ip")) {
-			strcpy(login_server_ip, w2);
-			ShowStatus ("set login_server_ip : %s\n", w2);
-		} else
-		if(!strcmpi(w1,"login_server_port")) {
-			login_server_port = atoi(w2);
-			ShowStatus ("set login_server_port : %s\n", w2);
-		} else
-		if(!strcmpi(w1,"login_server_id")) {
-			strcpy(login_server_id, w2);
-			ShowStatus ("set login_server_id : %s\n", w2);
-		} else
-		if(!strcmpi(w1,"login_server_pw")) {
-			strcpy(login_server_pw, w2);
-			ShowStatus ("set login_server_pw : %s\n", w2);
-		} else
-		if(!strcmpi(w1,"login_server_db")) {
-			strcpy(login_server_db, w2);
-			ShowStatus ("set login_server_db : %s\n", w2);
-		}
 #ifndef TXT_SQL_CONVERT
 		else if(!strcmpi(w1,"party_share_level"))
 			party_share_level = atoi(w2);
@@ -297,38 +265,6 @@ int inter_log(char* fmt, ...)
 	return 0;
 }
 
-/*=============================================
- * Does a mysql_ping to all connection handles
- *---------------------------------------------*/
-int inter_sql_ping(int tid, unsigned int tick, int id, intptr data) 
-{
-	ShowInfo("Pinging SQL server to keep connection alive...\n");
-	Sql_Ping(sql_handle);
-	if( char_gm_read )
-		Sql_Ping(lsql_handle);
-	return 0;
-}
-
-
-int sql_ping_init(void)
-{
-	uint32 connection_timeout, connection_ping_interval;
-
-	// set a default value first
-	connection_timeout = 28800; // 8 hours
-
-	// ask the mysql server for the timeout value
-	if( SQL_SUCCESS == Sql_GetTimeout(sql_handle, &connection_timeout) && connection_timeout < 60 )
-		connection_timeout = 60;
-
-	// establish keepalive
-	connection_ping_interval = connection_timeout - 30; // 30-second reserve
-	add_timer_func_list(inter_sql_ping, "inter_sql_ping");
-	add_timer_interval(gettick() + connection_ping_interval*1000, inter_sql_ping, 0, 0, connection_ping_interval*1000);
-
-	return 0;
-}
-
 #endif //TXT_SQL_CONVERT
 
 // initialize
@@ -348,34 +284,10 @@ int inter_init_sql(const char *file)
 		Sql_Free(sql_handle);
 		exit(EXIT_FAILURE);
 	}
-#ifndef TXT_SQL_CONVERT
-	else if (inter_sql_test()) {
-		ShowStatus("Connect Success! (Character Server)\n");
-	}
 
-	if(char_gm_read) {
-		lsql_handle = Sql_Malloc();
-		ShowInfo("Connect Character DB server.... (login server)\n");
-		if( SQL_ERROR == Sql_Connect(lsql_handle, login_server_id, login_server_pw, login_server_ip, (uint16)login_server_port, login_server_db) )
-		{
-			Sql_ShowDebug(lsql_handle);
-			Sql_Free(lsql_handle);
-			Sql_Free(sql_handle);
-			exit(EXIT_FAILURE);
-		}
-		else
-		{
-			ShowStatus ("Connect Success! (Login Server)\n");
-		}
-	}
-#endif //TXT_SQL_CONVERT
 	if( *default_codepage ) {
 		if( SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) )
 			Sql_ShowDebug(sql_handle);
-#ifndef TXT_SQL_CONVERT
-		if( char_gm_read && SQL_ERROR == Sql_SetEncoding(lsql_handle, default_codepage) )
-			Sql_ShowDebug(lsql_handle);
-#endif //TXT_SQL_CONVERT
 	}
 
 #ifndef TXT_SQL_CONVERT
@@ -389,46 +301,11 @@ int inter_init_sql(const char *file)
 	inter_mail_sql_init();
 	inter_auction_sql_init();
 
-	sql_ping_init();
 #endif //TXT_SQL_CONVERT
 	return 0;
 }
 #ifndef TXT_SQL_CONVERT
 
-int inter_sql_test (void)
-{
-	const char fields[][24] = {
-		"father",	// version 1363
-		"fame",		// version 1491
-	};	
-	char buf[1024] = "";
-	char* p;
-	size_t len;
-	int i;
-
-	if( SQL_ERROR == Sql_GetColumnNames(sql_handle, char_db, buf, sizeof(buf), '\n') )
-		Sql_ShowDebug(sql_handle);
-
-	// check DB strings
-	for( i = 0; i < ARRAYLENGTH(fields); ++i )
-	{
-		len = strlen(fields[i]);
-		p = strstr(buf, fields[i]);
-		while( p != NULL && p[len] != '\n' )
-			p = strstr(p, fields[i]);
-		if( p == NULL )
-		{
-			ShowSQL ("Field `%s` not be found in `%s`. Consider updating your database!\n", fields[i], char_db);
-			if( lsql_handle )
-				Sql_Free(lsql_handle);
-			Sql_Free(sql_handle);
-			exit(EXIT_FAILURE);
-		}
-	}
-
-	return 1;
-}
-
 // finalize
 void inter_final(void)
 {
@@ -533,26 +410,6 @@ int mapif_account_reg_reply(int fd,int account_id,int char_id, int type)
 	return 0;
 }
 
-int mapif_send_gmaccounts()
-{
-	int i, len = 4;
-	unsigned char buf[32000];
-
-	// forward the gm accounts to the map server
-	len = 4;
-	WBUFW(buf,0) = 0x2b15;
-				
-	for(i = 0; i < GM_num; i++) {
-		WBUFL(buf,len) = gm_account[i].account_id;
-		WBUFB(buf,len+4) = (uint8)gm_account[i].level;
-		len += 5;
-	}
-	WBUFW(buf,2) = len;
-	mapif_sendall(buf, len);
-
-	return 0;
-}
-
 //Request to kick char from a certain map server. [Skotlex]
 int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason)
 {
@@ -815,6 +672,26 @@ int mapif_parse_NameChangeRequest(int fd)
 }
 
 //--------------------------------------------------------
+
+/// Returns the length of the next complete packet to process,
+/// or 0 if no complete packet exists in the queue.
+///
+/// @param length The minimum allowed length, or -1 for dynamic lookup
+int inter_check_length(int fd, int length)
+{
+	if( length == -1 )
+	{// variable-length packet
+		if( RFIFOREST(fd) < 4 )
+			return 0;
+		length = RFIFOW(fd,2);
+	}
+
+	if( (int)RFIFOREST(fd) < length )
+		return 0;
+
+	return length;
+}
+
 int inter_parse_frommap(int fd)
 {
 	int cmd;
@@ -855,18 +732,4 @@ int inter_parse_frommap(int fd)
 	return 1;
 }
 
-// RFIFO check
-int inter_check_length(int fd, int length)
-{
-	if(length == -1) {	// v-len packet
-		if(RFIFOREST(fd) < 4)	// packet not yet
-			return 0;
-		length = RFIFOW(fd, 2);
-	}
-
-	if((int)RFIFOREST(fd) < length)	// packet not yet
-		return 0;
-
-	return length;
-}
 #endif //TXT_SQL_CONVERT

+ 0 - 15
src/char_sql/inter.h

@@ -14,30 +14,15 @@ int inter_mapif_init(int fd);
 int mapif_send_gmaccounts(void);
 int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason);
 
-int inter_check_length(int fd,int length);
-
 int inter_log(char *fmt,...);
 
 #define inter_cfgName "conf/inter_athena.conf"
 
 extern unsigned int party_share_level;
-extern char inter_log_filename[1024];
 
 extern Sql* sql_handle;
 extern Sql* lsql_handle;
 
-extern int char_server_port;
-extern char char_server_ip[32];
-extern char char_server_id[32];
-extern char char_server_pw[32];
-extern char char_server_db[32];
-
-extern int login_db_server_port;
-extern char login_db_server_ip[32];
-extern char login_db_server_id[32];
-extern char login_db_server_pw[32];
-extern char login_db_server_db[32];
-
 extern char main_chat_nick[16];
 
 int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type);

+ 1 - 5
src/common/mmo.h

@@ -90,6 +90,7 @@
 //Limits to avoid ID collision with other game objects
 #define START_ACCOUNT_NUM 2000000
 #define END_ACCOUNT_NUM 100000000
+#define START_CHAR_NUM 150000
 
 //Base Homun skill.
 #define HM_SKILLBASE 8001
@@ -344,11 +345,6 @@ struct registry {
 	struct global_reg account2[ACCOUNT_REG2_NUM];
 };
 
-struct gm_account {
-	int account_id;
-	int level;
-};
-
 struct party_member {
 	int account_id;
 	int char_id;

+ 1 - 1
src/common/plugins.c

@@ -287,7 +287,7 @@ char *DLL_ERROR(void)
 {
 	static char dllbuf[80];
 	DWORD dw = GetLastError();
-	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, 0, dllbuf, 80, NULL);
+	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, 0, dllbuf, 80, NULL);
 	return dllbuf;
 }
 #endif

+ 1 - 1
src/common/plugins.h

@@ -16,7 +16,7 @@
 
 	#define WIN32_LEAN_AND_MEAN
 	#include <windows.h>
-	#define DLL_OPEN(x)		LoadLibrary(x)
+	#define DLL_OPEN(x)		LoadLibraryA(x)
 	#define DLL_SYM(x,y)	GetProcAddress(x,y)
 	#define DLL_CLOSE(x)	FreeLibrary(x)
 	char *DLL_ERROR(void);

+ 51 - 0
src/common/sql.c

@@ -5,6 +5,7 @@
 #include "../common/malloc.h"
 #include "../common/showmsg.h"
 #include "../common/strlib.h"
+#include "../common/timer.h"
 #include "sql.h"
 
 #ifdef WIN32
@@ -24,6 +25,7 @@ struct Sql
 	MYSQL_RES* result;
 	MYSQL_ROW row;
 	unsigned long* lengths;
+	int keepalive;
 };
 
 
@@ -73,6 +75,8 @@ Sql* Sql_Malloc(void)
 
 
 
+static int Sql_P_Keepalive(Sql* self);
+
 /// Establishes a connection.
 int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db)
 {
@@ -85,6 +89,14 @@ int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* hos
 		ShowSQL("%s\n", mysql_error(&self->handle));
 		return SQL_ERROR;
 	}
+
+	self->keepalive = Sql_P_Keepalive(self);
+	if( self->keepalive == INVALID_TIMER )
+	{
+		ShowSQL("Failed to establish keepalive for DB connection!\n");
+		return SQL_ERROR;
+	}
+
 	return SQL_SUCCESS;
 }
 
@@ -162,6 +174,44 @@ int Sql_Ping(Sql* self)
 
 
 
+/// Wrapper function for Sql_Ping.
+///
+/// @private
+static int Sql_P_KeepaliveTimer(int tid, unsigned int tick, int id, intptr data)
+{
+	Sql* self = (Sql*)data;
+	ShowInfo("Pinging SQL server to keep connection alive...\n");
+	Sql_Ping(self);
+	return 0;
+}
+
+
+
+/// Establishes keepalive (periodic ping) on the connection.
+///
+/// @return the keepalive timer id, or INVALID_TIMER
+/// @private
+static int Sql_P_Keepalive(Sql* self)
+{
+	uint32 timeout, ping_interval;
+
+	// set a default value first
+	timeout = 28800; // 8 hours
+
+	// request the timeout value from the mysql server
+	Sql_GetTimeout(self, &timeout);
+
+	if( timeout < 60 )
+		timeout = 60;
+
+	// establish keepalive
+	ping_interval = timeout - 30; // 30-second reserve
+	//add_timer_func_list(Sql_P_KeepaliveTimer, "Sql_P_KeepaliveTimer");
+	return add_timer_interval(gettick() + ping_interval*1000, Sql_P_KeepaliveTimer, 0, (int)self, ping_interval*1000);
+}
+
+
+
 /// Escapes a string.
 size_t Sql_EscapeString(Sql* self, char *out_to, const char *from)
 {
@@ -356,6 +406,7 @@ void Sql_Free(Sql* self)
 	{
 		Sql_FreeResult(self);
 		StringBuf_Destroy(&self->buf);
+		delete_timer(self->keepalive, Sql_P_KeepaliveTimer);
 		aFree(self);
 	}
 }

+ 3 - 3
src/common/utils.c

@@ -77,7 +77,7 @@ static char* checkpath(char *path, const char *srcpath)
 
 void findfile(const char *p, const char *pat, void (func)(const char*))
 {	
-	WIN32_FIND_DATA FindFileData;
+	WIN32_FIND_DATAA FindFileData;
 	HANDLE hFind;
 	char tmppath[MAX_PATH+1];
 	
@@ -90,7 +90,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
 	else
 		strcat(tmppath, "*");
 	
-	hFind = FindFirstFile(tmppath, &FindFileData);
+	hFind = FindFirstFileA(tmppath, &FindFileData);
 	if (hFind != INVALID_HANDLE_VALUE)
 	{
 		do
@@ -111,7 +111,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*))
 			{
 				findfile(tmppath, pat, func);
 			}
-		}while (FindNextFile(hFind, &FindFileData) != 0);
+		}while (FindNextFileA(hFind, &FindFileData) != 0);
 		FindClose(hFind);
 	}
 	return;

File diff suppressed because it is too large
+ 275 - 626
src/ladmin/ladmin.c


+ 49 - 14
src/login/Makefile.in

@@ -10,36 +10,71 @@ COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h
 	../common/grfio.h ../common/mapindex.h \
 	../common/ers.h ../common/md5calc.h
 
-LOGIN_OBJ = obj_txt/login.o obj_txt/admin.o
-LOGIN_H = login.h
+COMMON_SQL_OBJ = ../common/obj_sql/sql.o
+COMMON_SQL_H = ../common/sql.h
+
+LOGIN_OBJ = login.o admin.o
+LOGIN_TXT_OBJ = $(LOGIN_OBJ:%=obj_txt/%) \
+	obj_txt/account_txt.o obj_txt/ipban_txt.o obj_txt/loginlog_txt.o
+LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) \
+	obj_sql/account_sql.o obj_sql/ipban_sql.o obj_sql/loginlog_sql.o
+LOGIN_H = login.h account.h ipban.h loginlog.h
+
+HAVE_MYSQL=@HAVE_MYSQL@
+ifeq ($(HAVE_MYSQL),yes)
+	LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ)
+else
+	LOGIN_SERVER_SQL_DEPENDS=needs_mysql
+endif
 
 @SET_MAKE@
 
 #####################################################################
-.PHONY : all login-server clean help
+.PHONY :all txt sql clean help
 
-all: login-server
+all: txt sql
 
-login-server: obj_txt $(LOGIN_OBJ) $(COMMON_OBJ)
-	@CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_OBJ) $(COMMON_OBJ) @LIBS@ 
+txt: obj_txt login-server
+
+sql: obj_sql login-server_sql
 
 clean:
-	rm -rf *.o obj_txt ../../login-server@EXEEXT@
+	rm -rf *.o obj_txt obj_sql ../../login-server@EXEEXT@ ../../login-server_sql@EXEEXT@
 
 help:
-	@echo "possible targets are 'login-server' 'all' 'clean' 'help'"
-	@echo "'login-server'  - login server (TXT version)"
-	@echo "'all'           - builds all above targets"
-	@echo "'clean'         - cleans builds and objects"
-	@echo "'help'          - outputs this message"
+	@echo "possible targets are 'sql' 'txt' 'all' 'clean' 'help'"
+	@echo "'sql'       - login server (SQL version)"
+	@echo "'txt'       - login server (TXT version)"
+	@echo "'all'       - builds all above targets"
+	@echo "'clean'     - cleans builds and objects"
+	@echo "'help'      - outputs this message"
 
 #####################################################################
 
+needs_mysql:
+	@echo "MySQL not found or disabled by the configure script"
+	@exit 1
+
+# object directories
 obj_txt:
-	-mkdir obj_txt
+	test -d obj_txt || mkdir obj_txt
 
+obj_sql:
+	test -d obj_sql || mkdir obj_sql
+
+#executables
+login-server: $(LOGIN_TXT_OBJ) $(COMMON_OBJ)
+	@CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_TXT_OBJ) $(COMMON_OBJ) @LIBS@ 
+
+login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS)
+	@CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) @LIBS@ @MYSQL_LIBS@
+
+# login object files
 obj_txt/%.o: %.c $(LOGIN_H) $(COMMON_H)
-	@CC@ @CFLAGS@ $(CUSTOM_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+	@CC@ @CFLAGS@ $(CUSTOM_CFLAGS) -DWITH_TXT @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
+
+obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H)
+	@CC@ @CFLAGS@ $(CUSTOM_CFLAGS) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
 
 # missing common object files
 ../common/obj_all/%.o:

+ 159 - 0
src/login/account.h

@@ -0,0 +1,159 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef __ACCOUNT_H_INCLUDED__
+#define __ACCOUNT_H_INCLUDED__
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h" // ACCOUNT_REG2_NUM
+
+typedef struct AccountDB AccountDB;
+typedef struct AccountDBIterator AccountDBIterator;
+
+
+// standard engines
+#ifdef WITH_TXT
+AccountDB* account_db_txt(void);
+#endif
+#ifdef WITH_SQL
+AccountDB* account_db_sql(void);
+#endif
+// extra engines (will probably use the other txt functions)
+#define ACCOUNTDB_CONSTRUCTOR_(engine) account_db_##engine
+#define ACCOUNTDB_CONSTRUCTOR(engine) ACCOUNTDB_CONSTRUCTOR_(engine)
+#ifdef ACCOUNTDB_ENGINE_0
+AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_0)(void);
+#endif
+#ifdef ACCOUNTDB_ENGINE_1
+AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_1)(void);
+#endif
+#ifdef ACCOUNTDB_ENGINE_2
+AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_2)(void);
+#endif
+#ifdef ACCOUNTDB_ENGINE_3
+AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_3)(void);
+#endif
+#ifdef ACCOUNTDB_ENGINE_4
+AccountDB* ACCOUNTDB_CONSTRUCTOR(ACCOUNTDB_ENGINE_4)(void);
+#endif
+
+
+struct mmo_account
+{
+	int account_id;
+	char userid[24];
+	char pass[32+1];        // 23+1 for plaintext, 32+1 for md5-ed passwords
+	char sex;               // gender (M/F/S)
+	char email[40];         // e-mail (by default: a@a.com)
+	int level;              // GM level
+	unsigned int state;     // packet 0x006a value + 1 (0: compte OK)
+	time_t unban_time;      // (timestamp): ban time limit of the account (0 = no ban)
+	time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited)
+	unsigned int logincount;// number of successful auth attempts
+	char lastlogin[24];     // date+time of last successful login
+	char last_ip[16];       // save of last IP of connection
+	int account_reg2_num;
+	struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
+};
+
+
+struct AccountDBIterator
+{
+	/// Destroys this iterator, releasing all allocated memory (including itself).
+	///
+	/// @param self Iterator
+	void (*destroy)(AccountDBIterator* self);
+
+	/// Fetches the next account in the database.
+	/// Fills acc with the account data.
+	/// @param self Iterator
+	/// @param acc Account data
+	/// @return true if successful
+	bool (*next)(AccountDBIterator* self, struct mmo_account* acc);
+};
+
+
+struct AccountDB
+{
+	/// Initializes this database, making it ready for use.
+	/// Call this after setting the properties.
+	///
+	/// @param self Database
+	/// @return true if successful
+	bool (*init)(AccountDB* self);
+
+	/// Destroys this database, releasing all allocated memory (including itself).
+	///
+	/// @param self Database
+	void (*destroy)(AccountDB* self);
+
+	/// Gets a property from this database.
+	/// These read-only properties must be implemented:
+	/// "engine.name" -> "txt", "sql", ...
+	/// "engine.version" -> internal version
+	/// "engine.comment" -> anything (suggestion: description or specs of the engine)
+	///
+	/// @param self Database
+	/// @param key Property name
+	/// @param buf Buffer for the value
+	/// @param buflen Buffer length
+	/// @return true if successful
+	bool (*get_property)(AccountDB* self, const char* key, char* buf, size_t buflen);
+
+	/// Sets a property in this database.
+	///
+	/// @param self Database
+	/// @param key Property name
+	/// @param value Property value
+	/// @return true if successful
+	bool (*set_property)(AccountDB* self, const char* key, const char* value);
+
+	/// Creates a new account in this database.
+	/// If acc->account_id is not -1, the provided value will be used.
+	/// Otherwise the account_id will be auto-generated and written to acc->account_id.
+	///
+	/// @param self Database
+	/// @param acc Account data
+	/// @return true if successful
+	bool (*create)(AccountDB* self, struct mmo_account* acc);
+
+	/// Removes an account from this database.
+	///
+	/// @param self Database
+	/// @param account_id Account id
+	/// @return true if successful
+	bool (*remove)(AccountDB* self, const int account_id);
+
+	/// Modifies the data of an existing account.
+	/// Uses acc->account_id to identify the account.
+	///
+	/// @param self Database
+	/// @param acc Account data
+	/// @return true if successful
+	bool (*save)(AccountDB* self, const struct mmo_account* acc);
+
+	/// Finds an account with account_id and copies it to acc.
+	///
+	/// @param self Database
+	/// @param acc Pointer that receives the account data
+	/// @param account_id Target account id
+	/// @return true if successful
+	bool (*load_num)(AccountDB* self, struct mmo_account* acc, const int account_id);
+
+	/// Finds an account with userid and copies it to acc.
+	///
+	/// @param self Database
+	/// @param acc Pointer that receives the account data
+	/// @param userid Target username
+	/// @return true if successful
+	bool (*load_str)(AccountDB* self, struct mmo_account* acc, const char* userid);
+
+	/// Returns a new forward iterator.
+	///
+	/// @param self Database
+	/// @return Iterator
+	AccountDBIterator* (*iterator)(AccountDB* self);
+};
+
+
+#endif // __ACCOUNT_H_INCLUDED__

+ 578 - 0
src/login/account_sql.c

@@ -0,0 +1,578 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/sql.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "account.h"
+#include <stdlib.h>
+#include <string.h>
+
+/// global defines
+#define ACCOUNT_SQL_DB_VERSION 20080417
+
+/// internal structure
+typedef struct AccountDB_SQL
+{
+	AccountDB vtable;    // public interface
+
+	Sql* accounts;       // SQL accounts storage
+
+	char db_hostname[32];
+	uint16 db_port;
+	char db_username[32];
+	char db_password[32];
+	char db_database[32];
+	char codepage[32];
+	bool case_sensitive;
+	char account_db[32];
+	char accreg_db[32];
+
+} AccountDB_SQL;
+
+/// internal structure
+typedef struct AccountDBIterator_SQL
+{
+	AccountDBIterator vtable;    // public interface
+
+	AccountDB_SQL* db;
+	int last_account_id;
+} AccountDBIterator_SQL;
+
+/// internal functions
+static bool account_db_sql_init(AccountDB* self);
+static void account_db_sql_destroy(AccountDB* self);
+static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen);
+static bool account_db_sql_set_property(AccountDB* self, const char* option, const char* value);
+static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc);
+static bool account_db_sql_remove(AccountDB* self, const int account_id);
+static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc);
+static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id);
+static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid);
+static AccountDBIterator* account_db_sql_iterator(AccountDB* self);
+static void account_db_sql_iter_destroy(AccountDBIterator* self);
+static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc);
+
+static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id);
+static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new);
+
+/// public constructor
+AccountDB* account_db_sql(void)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)aCalloc(1, sizeof(AccountDB_SQL));
+
+	// set up the vtable
+	db->vtable.init         = &account_db_sql_init;
+	db->vtable.destroy      = &account_db_sql_destroy;
+	db->vtable.get_property = &account_db_sql_get_property;
+	db->vtable.set_property = &account_db_sql_set_property;
+	db->vtable.save         = &account_db_sql_save;
+	db->vtable.create       = &account_db_sql_create;
+	db->vtable.remove       = &account_db_sql_remove;
+	db->vtable.load_num     = &account_db_sql_load_num;
+	db->vtable.load_str     = &account_db_sql_load_str;
+	db->vtable.iterator     = &account_db_sql_iterator;
+
+	// initialize to default values
+	db->accounts = NULL;
+	safestrncpy(db->db_hostname, "127.0.0.1", sizeof(db->db_hostname));
+	db->db_port = 3306;
+	safestrncpy(db->db_username, "ragnarok", sizeof(db->db_username));
+	safestrncpy(db->db_password, "ragnarok", sizeof(db->db_password));
+	safestrncpy(db->db_database, "ragnarok", sizeof(db->db_database));
+	safestrncpy(db->codepage, "", sizeof(db->codepage));
+	db->case_sensitive = false;
+	safestrncpy(db->account_db, "login", sizeof(db->account_db));
+	safestrncpy(db->accreg_db, "global_reg_value", sizeof(db->accreg_db));
+
+	return &db->vtable;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/// establishes database connection
+static bool account_db_sql_init(AccountDB* self)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	Sql* sql_handle;
+
+	db->accounts = Sql_Malloc();
+	sql_handle = db->accounts;
+
+	if( SQL_ERROR == Sql_Connect(sql_handle, db->db_username, db->db_password, db->db_hostname, db->db_port, db->db_database) )
+	{
+		Sql_ShowDebug(sql_handle);
+		Sql_Free(db->accounts);
+		db->accounts = NULL;
+		return false;
+	}
+
+	if( db->codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, db->codepage) )
+		Sql_ShowDebug(sql_handle);
+
+	return true;
+}	
+
+/// disconnects from database
+static void account_db_sql_destroy(AccountDB* self)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+
+	Sql_Free(db->accounts);
+	db->accounts = NULL;
+}
+
+/// Gets a property from this database.
+static bool account_db_sql_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	const char* signature = "account.sql.";
+
+	if( strcmp(key, "engine.name") == 0 )
+	{
+		safesnprintf(buf, buflen, "sql");
+		return true;
+	}
+	if( strcmp(key, "engine.version") == 0 )
+	{
+		safesnprintf(buf, buflen, "%d", ACCOUNT_SQL_DB_VERSION);
+		return true;
+	}
+	if( strcmp(key, "engine.comment") == 0 )
+	{
+		safesnprintf(buf, buflen, "SQL Account Database");
+		return true;
+	}
+
+	if( strncmp(key, signature, strlen(signature)) != 0 )
+		return false;
+
+	key += strlen(signature);
+
+	if( strcmpi(key, "db_hostname") == 0 )
+		safesnprintf(buf, buflen, "%s", db->db_hostname);
+	else
+	if( strcmpi(key, "db_port") == 0 )
+		safesnprintf(buf, buflen, "%d", db->db_port);
+	else
+	if( strcmpi(key, "db_username") == 0 )
+		safesnprintf(buf, buflen, "%s", db->db_username);
+	else
+	if( strcmpi(key, "db_password") == 0 )
+		safesnprintf(buf, buflen, "%s", db->db_password);
+	else
+	if( strcmpi(key, "db_database") == 0 )
+		safesnprintf(buf, buflen, "%s", db->db_database);
+	else
+	if( strcmpi(key, "codepage") == 0 )
+		safesnprintf(buf, buflen, "%s", db->codepage);
+	else
+	if( strcmpi(key, "case_sensitive") == 0 )
+		safesnprintf(buf, buflen, "%d", (db->case_sensitive ? 1 : 0));
+	else
+	if( strcmpi(key, "account_db") == 0 )
+		safesnprintf(buf, buflen, "%s", db->account_db);
+	else
+	if( strcmpi(key, "accreg_db") == 0 )
+		safesnprintf(buf, buflen, "%s", db->accreg_db);
+	else
+		return false;// not found
+
+	return true;
+}
+
+/// if the option is supported, adjusts the internal state
+static bool account_db_sql_set_property(AccountDB* self, const char* key, const char* value)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	const char* signature = "account.sql.";
+
+	if( strncmp(key, signature, strlen(signature)) != 0 )
+		return false;
+
+	key += strlen(signature);
+
+	if( strcmpi(key, "db_hostname") == 0 )
+		safestrncpy(db->db_hostname, value, sizeof(db->db_hostname));
+	else
+	if( strcmpi(key, "db_port") == 0 )
+		db->db_port = (uint16)strtoul(value, NULL, 10);
+	else
+	if( strcmpi(key, "db_username") == 0 )
+		safestrncpy(db->db_username, value, sizeof(db->db_username));
+	else
+	if( strcmpi(key, "db_password") == 0 )
+		safestrncpy(db->db_password, value, sizeof(db->db_password));
+	else
+	if( strcmpi(key, "db_database") == 0 )
+		safestrncpy(db->db_database, value, sizeof(db->db_database));
+	else
+	if( strcmpi(key, "codepage") == 0 )
+		safestrncpy(db->codepage, value, sizeof(db->codepage));
+	else
+	if( strcmpi(key, "case_sensitive") == 0 )
+		db->case_sensitive = config_switch(value);
+	else
+	if( strcmpi(key, "account_db") == 0 )
+		safestrncpy(db->account_db, value, sizeof(db->account_db));
+	else
+	if( strcmpi(key, "accreg_db") == 0 )
+		safestrncpy(db->accreg_db, value, sizeof(db->accreg_db));
+	else // no match
+		return false;
+
+	return true;
+}
+
+/// create a new account entry
+/// If acc->account_id is -1, the account id will be auto-generated,
+/// and its value will be written to acc->account_id if everything succeeds.
+static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	Sql* sql_handle = db->accounts;
+
+	// decide on the account id to assign
+	int account_id;
+	if( acc->account_id != -1 )
+	{// caller specifies it manually
+		account_id = acc->account_id;
+	}
+	else
+	{// ask the database
+		char* data;
+		size_t len;
+
+		if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) )
+		{
+			Sql_ShowDebug(sql_handle);
+			return false;
+		}
+		if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+		{
+			Sql_ShowDebug(sql_handle);
+			Sql_FreeResult(sql_handle);
+			return false;
+		}
+
+		Sql_GetData(sql_handle, 0, &data, &len);
+		account_id = ( data != NULL ) ? atoi(data) : 0;
+		Sql_FreeResult(sql_handle);
+
+		if( account_id < START_ACCOUNT_NUM )
+			account_id = START_ACCOUNT_NUM;
+
+	}
+
+	// zero value is prohibited
+	if( account_id == 0 )
+		return false;
+
+	// absolute maximum
+	if( account_id > END_ACCOUNT_NUM )
+		return false;
+
+	// insert the data into the database
+	acc->account_id = account_id;
+	return mmo_auth_tosql(db, acc, true);
+}
+
+/// delete an existing account entry + its regs
+static bool account_db_sql_remove(AccountDB* self, const int account_id)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	Sql* sql_handle = db->accounts;
+	bool result = false;
+
+	if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION")
+	||  SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id)
+	||  SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) )
+		Sql_ShowDebug(sql_handle);
+	else
+		result = true;
+
+	result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
+
+	return result;
+}
+
+/// update an existing account with the provided new data (both account and regs)
+static bool account_db_sql_save(AccountDB* self, const struct mmo_account* acc)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	return mmo_auth_tosql(db, acc, false);
+}
+
+/// retrieve data from db and store it in the provided data structure
+static bool account_db_sql_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	return mmo_auth_fromsql(db, acc, account_id);
+}
+
+/// retrieve data from db and store it in the provided data structure
+static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	Sql* sql_handle = db->accounts;
+	char esc_userid[2*NAME_LENGTH+1];
+	int account_id;
+	char* data;
+
+	Sql_EscapeString(sql_handle, esc_userid, userid);
+
+	// get the list of account IDs for this user ID
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'",
+		db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) )
+	{
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+
+	if( Sql_NumRows(sql_handle) > 1 )
+	{// serious problem - duplicit account
+		ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid);
+		Sql_FreeResult(sql_handle);
+		return false;
+	}
+
+	if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+	{// no such entry
+		Sql_FreeResult(sql_handle);
+		return false;
+	}
+
+	Sql_GetData(sql_handle, 0, &data, NULL);
+	account_id = atoi(data);
+
+	return account_db_sql_load_num(self, acc, account_id);
+}
+
+
+/// Returns a new forward iterator.
+static AccountDBIterator* account_db_sql_iterator(AccountDB* self)
+{
+	AccountDB_SQL* db = (AccountDB_SQL*)self;
+	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)aCalloc(1, sizeof(AccountDBIterator_SQL));
+
+	// set up the vtable
+	iter->vtable.destroy = &account_db_sql_iter_destroy;
+	iter->vtable.next    = &account_db_sql_iter_next;
+
+	// fill data
+	iter->db = db;
+	iter->last_account_id = -1;
+
+	return &iter->vtable;
+}
+
+
+/// Destroys this iterator, releasing all allocated memory (including itself).
+static void account_db_sql_iter_destroy(AccountDBIterator* self)
+{
+	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
+	aFree(iter);
+}
+
+
+/// Fetches the next account in the database.
+static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account* acc)
+{
+	AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self;
+	AccountDB_SQL* db = (AccountDB_SQL*)iter->db;
+	Sql* sql_handle = db->accounts;
+	int account_id;
+	char* data;
+
+	// get next account ID
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1",
+		db->account_db, iter->last_account_id) )
+	{
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+
+	if( SQL_SUCCESS == Sql_NextRow(sql_handle) &&
+		SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, NULL) &&
+		data != NULL )
+	{// get account data
+		account_id = atoi(data);
+		if( mmo_auth_fromsql(db, acc, account_id) )
+		{
+			iter->last_account_id = account_id;
+			Sql_FreeResult(sql_handle);
+			return true;
+		}
+	}
+	Sql_FreeResult(sql_handle);
+	return false;
+}
+
+
+static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int account_id)
+{
+	Sql* sql_handle = db->accounts;
+	char* data;
+	int i = 0;
+
+	// retrieve login entry for the specified account
+	if( SQL_ERROR == Sql_Query(sql_handle,
+	    "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`level`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip` FROM `%s` WHERE `account_id` = %d",
+		db->account_db, account_id )
+	) {
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+
+	if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+	{// no such entry
+		Sql_FreeResult(sql_handle);
+		return false;
+	}
+
+	Sql_GetData(sql_handle,  0, &data, NULL); acc->account_id = atoi(data);
+	Sql_GetData(sql_handle,  1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid));
+	Sql_GetData(sql_handle,  2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass));
+	Sql_GetData(sql_handle,  3, &data, NULL); acc->sex = data[0];
+	Sql_GetData(sql_handle,  4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email));
+	Sql_GetData(sql_handle,  5, &data, NULL); acc->level = atoi(data);
+	Sql_GetData(sql_handle,  6, &data, NULL); acc->state = strtoul(data, NULL, 10);
+	Sql_GetData(sql_handle,  7, &data, NULL); acc->unban_time = atol(data);
+	Sql_GetData(sql_handle,  8, &data, NULL); acc->expiration_time = atol(data);
+	Sql_GetData(sql_handle,  9, &data, NULL); acc->logincount = strtoul(data, NULL, 10);
+	Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin));
+	Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip));
+
+	Sql_FreeResult(sql_handle);
+
+
+	// retrieve account regs for the specified user
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
+	{
+		Sql_ShowDebug(sql_handle);
+		return false;
+	}
+
+	acc->account_reg2_num = (int)Sql_NumRows(sql_handle);
+
+	while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
+	{
+		char* data;
+		Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str));
+		Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value));
+		++i;
+	}
+	Sql_FreeResult(sql_handle);
+
+	if( i != acc->account_reg2_num )
+		return false;
+
+	return true;
+}
+
+static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, bool is_new)
+{
+	Sql* sql_handle = db->accounts;
+	SqlStmt* stmt = SqlStmt_Malloc(sql_handle);
+	bool result = false;
+	int i;
+
+	// try
+	do
+	{
+
+	if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") )
+	{
+		Sql_ShowDebug(sql_handle);
+		break;
+	}
+
+	if( is_new )
+	{// insert into account table
+		if( SQL_SUCCESS != SqlStmt_Prepare(stmt,
+			"INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `level`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+			db->account_db)
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_INT,    (void*)&acc->account_id,      sizeof(acc->account_id))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  2, SQLDT_STRING, (void*)acc->pass,             strlen(acc->pass))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  3, SQLDT_ENUM,   (void*)&acc->sex,             sizeof(acc->sex))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  4, SQLDT_STRING, (void*)&acc->email,           strlen(acc->email))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  5, SQLDT_INT,    (void*)&acc->level,           sizeof(acc->level))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  6, SQLDT_UINT,   (void*)&acc->state,           sizeof(acc->state))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  7, SQLDT_LONG,   (void*)&acc->unban_time,      sizeof(acc->unban_time))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  8, SQLDT_INT,    (void*)&acc->expiration_time, sizeof(acc->expiration_time))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
+		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
+		) {
+			SqlStmt_ShowDebug(stmt);
+			break;
+		}
+	}
+	else
+	{// update account table
+		stmt = SqlStmt_Malloc(sql_handle);
+		if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`level`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id)
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  0, SQLDT_STRING, (void*)acc->userid,           strlen(acc->userid))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  1, SQLDT_STRING, (void*)acc->pass,             strlen(acc->pass))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  2, SQLDT_ENUM,   (void*)&acc->sex,             sizeof(acc->sex))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  3, SQLDT_STRING, (void*)acc->email,            strlen(acc->email))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  4, SQLDT_INT,    (void*)&acc->level,           sizeof(acc->level))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  5, SQLDT_UINT,   (void*)&acc->state,           sizeof(acc->state))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  6, SQLDT_LONG,   (void*)&acc->unban_time,      sizeof(acc->unban_time))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  7, SQLDT_LONG,   (void*)&acc->expiration_time, sizeof(acc->expiration_time))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  8, SQLDT_UINT,   (void*)&acc->logincount,      sizeof(acc->logincount))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt,  9, SQLDT_STRING, (void*)&acc->lastlogin,       strlen(acc->lastlogin))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip,         strlen(acc->last_ip))
+		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
+		) {
+			SqlStmt_ShowDebug(stmt);
+			break;
+		}
+	}
+
+	// remove old account regs
+	if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) )
+	{
+		Sql_ShowDebug(sql_handle);
+		break;
+	}
+	// insert new account regs
+	if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ? );",  db->accreg_db, acc->account_id) )
+	{
+		SqlStmt_ShowDebug(stmt);
+		break;
+	}
+	for( i = 0; i < acc->account_reg2_num; ++i )
+	{
+		if( SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->account_reg2[i].str, strlen(acc->account_reg2[i].str))
+		||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->account_reg2[i].value, strlen(acc->account_reg2[i].value))
+		||  SQL_SUCCESS != SqlStmt_Execute(stmt)
+		) {
+			SqlStmt_ShowDebug(stmt);
+			break;
+		}
+	}
+	if( i < acc->account_reg2_num )
+	{
+		result = false;
+		break;
+	}
+
+	// if we got this far, everything was successful
+	result = true;
+
+	} while(0);
+	// finally
+
+	result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") );
+	SqlStmt_Free(stmt);
+
+	return result;
+}

+ 622 - 0
src/login/account_txt.c

@@ -0,0 +1,622 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/db.h"
+#include "../common/lock.h"
+#include "../common/malloc.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "account.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/// global defines
+#define ACCOUNT_TXT_DB_VERSION 20080409
+#define AUTHS_BEFORE_SAVE 10 // flush every 10 saves
+#define AUTH_SAVING_INTERVAL 60000 // flush every 10 minutes
+
+/// internal structure
+typedef struct AccountDB_TXT
+{
+	AccountDB vtable;      // public interface
+
+	DBMap* accounts;       // in-memory accounts storage
+	int next_account_id;   // auto_increment
+	int auths_before_save; // prevents writing to disk too often
+	int save_timer;        // save timer id
+
+	char account_db[1024]; // account data storage file
+	bool case_sensitive;   // how to look up usernames
+
+} AccountDB_TXT;
+
+/// internal structure
+typedef struct AccountDBIterator_TXT
+{
+	AccountDBIterator vtable;      // public interface
+
+	DBIterator* iter;
+} AccountDBIterator_TXT;
+
+/// internal functions
+static bool account_db_txt_init(AccountDB* self);
+static void account_db_txt_destroy(AccountDB* self);
+static bool account_db_txt_get_property(AccountDB* self, const char* key, char* buf, size_t buflen);
+static bool account_db_txt_set_property(AccountDB* self, const char* option, const char* value);
+static bool account_db_txt_create(AccountDB* self, struct mmo_account* acc);
+static bool account_db_txt_remove(AccountDB* self, const int account_id);
+static bool account_db_txt_save(AccountDB* self, const struct mmo_account* acc);
+static bool account_db_txt_load_num(AccountDB* self, struct mmo_account* acc, const int account_id);
+static bool account_db_txt_load_str(AccountDB* self, struct mmo_account* acc, const char* userid);
+static AccountDBIterator* account_db_txt_iterator(AccountDB* self);
+static void account_db_txt_iter_destroy(AccountDBIterator* self);
+static bool account_db_txt_iter_next(AccountDBIterator* self, struct mmo_account* acc);
+
+static bool mmo_auth_fromstr(struct mmo_account* acc, char* str, unsigned int version);
+static bool mmo_auth_tostr(const struct mmo_account* acc, char* str);
+static void mmo_auth_sync(AccountDB_TXT* self);
+static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data);
+
+/// public constructor
+AccountDB* account_db_txt(void)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)aCalloc(1, sizeof(AccountDB_TXT));
+
+	// set up the vtable
+	db->vtable.init         = &account_db_txt_init;
+	db->vtable.destroy      = &account_db_txt_destroy;
+	db->vtable.get_property = &account_db_txt_get_property;
+	db->vtable.set_property = &account_db_txt_set_property;
+	db->vtable.save         = &account_db_txt_save;
+	db->vtable.create       = &account_db_txt_create;
+	db->vtable.remove       = &account_db_txt_remove;
+	db->vtable.load_num     = &account_db_txt_load_num;
+	db->vtable.load_str     = &account_db_txt_load_str;
+	db->vtable.iterator     = &account_db_txt_iterator;
+
+	// initialize to default values
+	db->accounts = NULL;
+	db->next_account_id = START_ACCOUNT_NUM;
+	db->auths_before_save = AUTHS_BEFORE_SAVE;
+	db->save_timer = INVALID_TIMER;
+	safestrncpy(db->account_db, "save/account.txt", sizeof(db->account_db));
+	db->case_sensitive = false;
+
+	return &db->vtable;
+}
+
+
+/* ------------------------------------------------------------------------- */
+
+
+/// opens accounts file, loads it, and starts a periodic saving timer
+static bool account_db_txt_init(AccountDB* self)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts;
+	FILE* fp;
+	char line[2048];
+	unsigned int version = 0;
+
+	// create accounts database
+	db->accounts = idb_alloc(DB_OPT_RELEASE_DATA);
+	accounts = db->accounts;
+
+	// open data file
+	fp = fopen(db->account_db, "r");
+	if( fp == NULL )
+	{
+		// no account file -> no account -> no login, including char-server (ERROR)
+		ShowError(CL_RED"account_db_txt_init: Accounts file [%s] not found."CL_RESET"\n", db->account_db);
+		return false;
+	}
+
+	// load data file
+	while( fgets(line, sizeof(line), fp) != NULL )
+	{
+		int account_id, n;
+		unsigned int v;
+		struct mmo_account acc;
+		struct mmo_account* tmp;
+		struct DBIterator* iter;
+		int (*compare)(const char* str1, const char* str2) = ( db->case_sensitive ) ? strcmp : stricmp;
+
+		if( line[0] == '/' && line[1] == '/' )
+			continue;
+
+		if( sscanf(line, "%d%n", &v, &n) == 1 && line[n] == '\n' )
+		{// format version definition
+			version = v;
+			continue;
+		}
+
+		if( sscanf(line, "%d\t%%newid%%%n", &account_id, &n) == 1 && line[n] == '\n' )
+		{// auto-increment
+			if( account_id > db->next_account_id )
+				db->next_account_id = account_id;
+			continue;
+		}
+
+		if( !mmo_auth_fromstr(&acc, line, version) )
+		{
+			ShowError("account_db_txt_init: skipping invalid data: %s", line);
+			continue;
+		}
+
+		// apply constraints & checks here
+		if( acc.sex != 'S' && (acc.account_id < START_ACCOUNT_NUM || acc.account_id > END_ACCOUNT_NUM) )
+			ShowWarning("account_db_txt_init: account %d:'%s' has ID outside of the defined range for accounts (min:%d max:%d)!\n", acc.account_id, acc.userid, START_ACCOUNT_NUM, END_ACCOUNT_NUM);
+
+		iter = accounts->iterator(accounts);
+		for( tmp = (struct mmo_account*)iter->first(iter,NULL); iter->exists(iter); tmp = (struct mmo_account*)iter->next(iter,NULL) )
+			if( compare(acc.userid, tmp->userid) == 0 )
+					break;
+		iter->destroy(iter);
+
+		if( tmp != NULL )
+		{// entry with identical username
+			ShowWarning("account_db_txt_init: account %d:'%s' has same username as account %d. The account will be inaccessible!\n", acc.account_id, acc.userid, tmp->account_id);
+		}
+
+		if( idb_get(accounts, acc.account_id) != NULL )
+		{// account id already occupied
+			ShowError("account_db_txt_init: ID collision for account id %d! Discarding data for account '%s'...\n", acc.account_id, acc.userid);
+			continue;
+		}
+
+		// record entry in db
+		tmp = (struct mmo_account*)aMalloc(sizeof(struct mmo_account));
+		memcpy(tmp, &acc, sizeof(struct mmo_account));
+		idb_put(accounts, acc.account_id, tmp);
+
+		if( db->next_account_id < acc.account_id)
+			db->next_account_id = acc.account_id + 1;
+	}
+
+	// close data file
+	fclose(fp);
+
+	// initialize data saving timer
+	add_timer_func_list(mmo_auth_sync_timer, "mmo_auth_sync_timer");
+	db->save_timer = add_timer_interval(gettick() + AUTH_SAVING_INTERVAL, mmo_auth_sync_timer, 0, (int)db, AUTH_SAVING_INTERVAL);
+
+	return true;
+}
+
+/// flush accounts db, close savefile and deallocate structures
+static void account_db_txt_destroy(AccountDB* self)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+
+	// stop saving timer
+	delete_timer(db->save_timer, mmo_auth_sync_timer);
+
+	// write data
+	mmo_auth_sync(db);
+
+	// delete accounts database
+	accounts->destroy(accounts, NULL);
+	db->accounts = NULL;
+
+	// delete entire structure
+	aFree(db);
+}
+
+/// Gets a property from this database.
+static bool account_db_txt_get_property(AccountDB* self, const char* key, char* buf, size_t buflen)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	const char* signature = "account.txt.";
+
+	if( strcmp(key, "engine.name") == 0 )
+	{
+		safesnprintf(buf, buflen, "txt");
+		return true;
+	}
+	if( strcmp(key, "engine.version") == 0 )
+	{
+		safesnprintf(buf, buflen, "%d", ACCOUNT_TXT_DB_VERSION);
+		return true;
+	}
+	if( strcmp(key, "engine.comment") == 0 )
+	{
+		safesnprintf(buf, buflen, "TXT Account Database %d", ACCOUNT_TXT_DB_VERSION);
+		return true;
+	}
+
+	if( strncmp(key, signature, strlen(signature)) != 0 )
+		return false;
+
+	key += strlen(signature);
+
+	if( strcmpi(key, "account_db") == 0 )
+		safesnprintf(buf, buflen, "%s", db->account_db);
+	else if( strcmpi(key, "case_sensitive") == 0 )
+		safesnprintf(buf, buflen, "%d", (db->case_sensitive ? 1 : 0));
+	else
+		return false;// not found
+
+	return true;
+}
+
+/// Sets a property in this database.
+static bool account_db_txt_set_property(AccountDB* self, const char* key, const char* value)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	const char* signature = "account.txt.";
+
+	if( strncmp(key, signature, strlen(signature)) != 0 )
+		return false;
+
+	key += strlen(signature);
+
+	if( strcmpi(key, "account_db") == 0 )
+		safestrncpy(db->account_db, value, sizeof(db->account_db));
+	else if( strcmpi(key, "case_sensitive") == 0 )
+		db->case_sensitive = config_switch(value);
+	else // no match
+		return false;
+
+	return true;
+}
+
+/// Add a new entry for this account to the account db and save it.
+/// If acc->account_id is -1, the account id will be auto-generated,
+/// and its value will be written to acc->account_id if everything succeeds.
+static bool account_db_txt_create(AccountDB* self, struct mmo_account* acc)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+	struct mmo_account* tmp;
+
+	// decide on the account id to assign
+	int account_id = ( acc->account_id != -1 ) ? acc->account_id : db->next_account_id;
+
+	// absolute maximum
+	if( account_id > END_ACCOUNT_NUM )
+		return false;
+
+	// check if the account_id is free
+	tmp = idb_get(accounts, account_id);
+	if( tmp != NULL )
+	{// error condition - entry already present
+		ShowError("account_db_txt_create: cannot create account %d:'%s', this id is already occupied by %d:'%s'!\n", account_id, acc->userid, account_id, tmp->userid);
+		return false;
+	}
+
+	// copy the data and store it in the db
+	CREATE(tmp, struct mmo_account, 1);
+	memcpy(tmp, acc, sizeof(struct mmo_account));
+	tmp->account_id = account_id;
+	idb_put(accounts, account_id, tmp);
+
+	// increment the auto_increment value
+	if( account_id >= db->next_account_id )
+		db->next_account_id = account_id + 1;
+
+	// flush data
+	mmo_auth_sync(db);
+
+	// write output
+	acc->account_id = account_id;
+
+	return true;
+}
+
+/// find an existing entry for this account id and delete it
+static bool account_db_txt_remove(AccountDB* self, const int account_id)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+
+	//TODO: find out if this really works
+	struct mmo_account* tmp = idb_remove(accounts, account_id);
+	if( tmp == NULL )
+	{// error condition - entry not present
+		ShowError("account_db_txt_remove: no such account with id %d\n", account_id);
+		return false;
+	}
+
+	// flush data
+	mmo_auth_sync(db);
+
+	return true;
+}
+
+/// rewrite the data stored in the account_db with the one provided
+static bool account_db_txt_save(AccountDB* self, const struct mmo_account* acc)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+	int account_id = acc->account_id;
+
+	// retrieve previous data
+	struct mmo_acount* tmp = idb_get(accounts, account_id);
+	if( tmp == NULL )
+	{// error condition - entry not found
+		return false;
+	}
+	
+	// overwrite with new data
+	memcpy(tmp, acc, sizeof(struct mmo_account));
+
+	// modify save counter and save if needed
+	if( --db->auths_before_save == 0 )
+		mmo_auth_sync(db);
+
+	return true;
+}
+
+/// retrieve data from db and store it in the provided data structure
+static bool account_db_txt_load_num(AccountDB* self, struct mmo_account* acc, const int account_id)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+
+	// retrieve data
+	struct mmo_account* tmp = idb_get(accounts, account_id);
+	if( tmp == NULL )
+	{// entry not found
+		return false;
+	}
+
+	// store it
+	memcpy(acc, tmp, sizeof(struct mmo_account));
+
+	return true;
+}
+
+/// retrieve data from db and store it in the provided data structure
+static bool account_db_txt_load_str(AccountDB* self, struct mmo_account* acc, const char* userid)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+
+	// retrieve data
+	struct DBIterator* iter = accounts->iterator(accounts);
+	struct mmo_account* tmp;
+	int (*compare)(const char* str1, const char* str2) = ( db->case_sensitive ) ? strcmp : stricmp;
+
+	for( tmp = (struct mmo_account*)iter->first(iter,NULL); iter->exists(iter); tmp = (struct mmo_account*)iter->next(iter,NULL) )
+		if( compare(userid, tmp->userid) == 0 )
+			break;
+	iter->destroy(iter);
+
+	if( tmp == NULL )
+	{// entry not found
+		return false;
+	}
+
+	// store it
+	memcpy(acc, tmp, sizeof(struct mmo_account));
+
+	return true;
+}
+
+
+/// Returns a new forward iterator.
+static AccountDBIterator* account_db_txt_iterator(AccountDB* self)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)self;
+	DBMap* accounts = db->accounts;
+	AccountDBIterator_TXT* iter = (AccountDBIterator_TXT*)aCalloc(1, sizeof(AccountDBIterator_TXT));
+
+	// set up the vtable
+	iter->vtable.destroy = &account_db_txt_iter_destroy;
+	iter->vtable.next    = &account_db_txt_iter_next;
+
+	// fill data
+	iter->iter = db_iterator(accounts);
+
+	return &iter->vtable;
+}
+
+
+/// Destroys this iterator, releasing all allocated memory (including itself).
+static void account_db_txt_iter_destroy(AccountDBIterator* self)
+{
+	AccountDBIterator_TXT* iter = (AccountDBIterator_TXT*)self;
+	dbi_destroy(iter->iter);
+	aFree(iter);
+}
+
+
+/// Fetches the next account in the database.
+static bool account_db_txt_iter_next(AccountDBIterator* self, struct mmo_account* acc)
+{
+	AccountDBIterator_TXT* iter = (AccountDBIterator_TXT*)self;
+	struct mmo_account* tmp = (struct mmo_account*)dbi_next(iter->iter);
+	if( dbi_exists(iter->iter) )
+	{
+		memcpy(acc, tmp, sizeof(struct mmo_account));
+		return true;
+	}
+	return false;
+}
+
+
+/// parse input string into the provided account data structure
+static bool mmo_auth_fromstr(struct mmo_account* a, char* str, unsigned int version)
+{
+	char* fields[32];
+	int count;
+	char* regs;
+	int i, n;
+
+	// zero out the destination first
+	memset(a, 0x00, sizeof(struct mmo_account));
+
+	// extract tab-separated columns from line
+	count = sv_split(str, strlen(str), 0, '\t', fields, ARRAYLENGTH(fields), SV_NOESCAPE_NOTERMINATE);
+
+	if( version == ACCOUNT_TXT_DB_VERSION && count == 13 )
+	{
+		a->account_id = strtol(fields[1], NULL, 10);
+		safestrncpy(a->userid, fields[2], sizeof(a->userid));
+		safestrncpy(a->pass, fields[3], sizeof(a->pass));
+		a->sex = fields[4][0];
+		safestrncpy(a->email, fields[5], sizeof(a->email));
+		a->level = strtoul(fields[6], NULL, 10);
+		a->state = strtoul(fields[7], NULL, 10);
+		a->unban_time = strtol(fields[8], NULL, 10);
+		a->expiration_time = strtol(fields[9], NULL, 10);
+		a->logincount = strtoul(fields[10], NULL, 10);
+		safestrncpy(a->lastlogin, fields[11], sizeof(a->lastlogin));
+		safestrncpy(a->last_ip, fields[12], sizeof(a->last_ip));
+		regs = fields[13];
+	}
+	else
+	if( version == 0 && count == 14 )
+	{
+		a->account_id = strtol(fields[1], NULL, 10);
+		safestrncpy(a->userid, fields[2], sizeof(a->userid));
+		safestrncpy(a->pass, fields[3], sizeof(a->pass));
+		safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin));
+		a->sex = fields[5][0];
+		a->logincount = strtoul(fields[6], NULL, 10);
+		a->state = strtoul(fields[7], NULL, 10);
+		safestrncpy(a->email, fields[8], sizeof(a->email));
+		//safestrncpy(a->error_message, fields[9], sizeof(a->error_message));
+		a->expiration_time = strtol(fields[10], NULL, 10);
+		safestrncpy(a->last_ip, fields[11], sizeof(a->last_ip));
+		//safestrncpy(a->memo, fields[12], sizeof(a->memo));
+		a->unban_time = strtol(fields[13], NULL, 10);
+		regs = fields[14];
+	}
+	else
+	if( version == 0 && count == 13 )
+	{
+		a->account_id = strtol(fields[1], NULL, 10);
+		safestrncpy(a->userid, fields[2], sizeof(a->userid));
+		safestrncpy(a->pass, fields[3], sizeof(a->pass));
+		safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin));
+		a->sex = fields[5][0];
+		a->logincount = strtoul(fields[6], NULL, 10);
+		a->state = strtoul(fields[7], NULL, 10);
+		safestrncpy(a->email, fields[8], sizeof(a->email));
+		//safestrncpy(a->error_message, fields[9], sizeof(a->error_message));
+		a->expiration_time = strtol(fields[10], NULL, 10);
+		safestrncpy(a->last_ip, fields[11], sizeof(a->last_ip));
+		//safestrncpy(a->memo, fields[12], sizeof(a->memo));
+		regs = fields[13];
+	}
+	else
+	if( version == 0 && count == 8 )
+	{
+		a->account_id = strtol(fields[1], NULL, 10);
+		safestrncpy(a->userid, fields[2], sizeof(a->userid));
+		safestrncpy(a->pass, fields[3], sizeof(a->pass));
+		safestrncpy(a->lastlogin, fields[4], sizeof(a->lastlogin));
+		a->sex = fields[5][0];
+		a->logincount = strtoul(fields[6], NULL, 10);
+		a->state = strtoul(fields[7], NULL, 10);
+		regs = fields[8];
+	}
+	else
+	{// unmatched row
+		return false;
+	}
+
+	// extract account regs
+	// {reg name<COMMA>reg value<SPACE>}*
+	n = 0;
+	for( i = 0; i < ACCOUNT_REG2_NUM; ++i )
+	{
+		char key[32];
+		char value[256];
+	
+		regs += n;
+
+		if (sscanf(regs, "%31[^\t,],%255[^\t ] %n", key, value, &n) != 2)
+		{
+			// We must check if a str is void. If it's, we can continue to read other REG2.
+			// Account line will have something like: str2,9 ,9 str3,1 (here, ,9 is not good)
+			if (regs[0] == ',' && sscanf(regs, ",%[^\t ] %n", value, &n) == 1) { 
+				i--;
+				continue;
+			} else
+				break;
+		}
+		
+		safestrncpy(a->account_reg2[i].str, key, 32);
+		safestrncpy(a->account_reg2[i].value, value, 256);
+	}
+	a->account_reg2_num = i;
+
+	return true;
+}
+
+/// dump the contents of the account data structure into the provided string buffer
+static bool mmo_auth_tostr(const struct mmo_account* a, char* str)
+{
+	int i;
+	char* str_p = str;
+
+	str_p += sprintf(str_p, "%d\t%s\t%s\t%c\t%s\t%u\t%u\t%ld\t%ld\t%u\t%s\t%s\t",
+	                 a->account_id, a->userid, a->pass, a->sex, a->email, a->level,
+	                 a->state, (long)a->unban_time, (long)a->expiration_time,
+	                 a->logincount, a->lastlogin, a->last_ip);
+
+	for( i = 0; i < a->account_reg2_num; ++i )
+		if( a->account_reg2[i].str[0] )
+			str_p += sprintf(str_p, "%s,%s ", a->account_reg2[i].str, a->account_reg2[i].value);
+
+	return true;
+}
+
+/// dump the entire account db to disk
+static void mmo_auth_sync(AccountDB_TXT* db)
+{
+	int lock;
+	FILE *fp;
+	struct DBIterator* iter;
+	struct mmo_account* acc;
+
+	fp = lock_fopen(db->account_db, &lock);
+	if( fp == NULL )
+	{
+		return;
+	}
+
+	fprintf(fp, "%d\n", ACCOUNT_TXT_DB_VERSION); // savefile version
+
+	fprintf(fp, "// Accounts file: here are saved all information about the accounts.\n");
+	fprintf(fp, "// Structure: account ID, username, password, sex, email, level, state, unban time, expiration time, # of logins, last login time, last (accepted) login ip, repeated(register key, register value)\n");
+	fprintf(fp, "// where:\n");
+	fprintf(fp, "//   sex             : M or F for normal accounts, S for server accounts\n");
+	fprintf(fp, "//   level           : this account's gm level\n");
+	fprintf(fp, "//   state           : 0: account is ok, 1 to 256: error code of packet 0x006a + 1\n");
+	fprintf(fp, "//   unban time      : 0: no ban, <other value>: banned until the date (unix timestamp)\n");
+	fprintf(fp, "//   expiration time : 0: unlimited account, <other value>: account expires on the date (unix timestamp)\n");
+
+	//TODO: sort?
+
+	iter = db->accounts->iterator(db->accounts);
+	for( acc = (struct mmo_account*)iter->first(iter,NULL); iter->exists(iter); acc = (struct mmo_account*)iter->next(iter,NULL) )
+	{
+		char buf[2048]; // ought to be big enough ^^
+		mmo_auth_tostr(acc, buf);
+		fprintf(fp, "%s\n", buf);
+	}
+	fprintf(fp, "%d\t%%newid%%\n", db->next_account_id);
+	iter->destroy(iter);
+
+	lock_fclose(fp, db->account_db, &lock);
+
+	// reset save counter
+	db->auths_before_save = AUTHS_BEFORE_SAVE;
+}
+
+static int mmo_auth_sync_timer(int tid, unsigned int tick, int id, intptr data)
+{
+	AccountDB_TXT* db = (AccountDB_TXT*)data;
+
+	if( db->auths_before_save < AUTHS_BEFORE_SAVE )
+		mmo_auth_sync(db); // db was modified, flush it
+
+	return 0;
+}

+ 294 - 312
src/login/admin.c

@@ -1,3 +1,6 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
 #include "../common/cbasetypes.h"
 #include "../common/mmo.h"
 #include "../common/core.h"
@@ -10,6 +13,7 @@
 #include "../common/version.h"
 #include "../common/md5calc.h"
 #include "../common/lock.h"
+#include "account.h"
 #include "login.h"
 
 #include <stdio.h>
@@ -17,31 +21,72 @@
 #include <string.h>
 #include <sys/stat.h> // for stat/lstat/fstat
 
-extern struct Login_Config login_config;
-
 #define MAX_SERVERS 30
 extern struct mmo_char_server server[MAX_SERVERS];
-extern struct mmo_account* auth_dat;
-extern uint32 auth_num;
-extern int account_id_count;
-extern char GM_account_filename[1024];
+extern AccountDB* accounts;
 
 int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len);
-int search_account_index(char* account_name);
-int mmo_auth_new(struct mmo_account* account);
-void mmo_auth_sync(void);
-int mmo_auth_tostr(char* str, struct mmo_account* p);
-int read_gm_account(void);
-void send_GM_accounts(int fd);
-int isGM(int account_id);
+bool check_password(const char* md5key, int passwdenc, const char* passwd, const char* refpass);
+int mmo_auth_new(const char* userid, const char* pass, const char sex, const char* last_ip);
+int parse_admin(int fd);
+
+
+bool ladmin_auth(struct login_session_data* sd, const char* ip)
+{
+	bool result = false;
+
+	if( str2ip(ip) != host2ip(login_config.admin_allowed_host) )
+		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - IP isn't authorised (ip: %s).\n", ip);
+	else
+	if( !login_config.admin_state )
+		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - remote administration is disabled (ip: %s)\n", ip);
+	else
+	if( !check_password(sd->md5key, sd->passwdenc, sd->passwd, login_config.admin_pass) )
+		ShowNotice("'ladmin'-login: Connection in administration mode REFUSED - invalid password (ip: %s)\n", ip);
+	else
+	{
+		ShowNotice("'ladmin'-login: Connection in administration mode accepted (ip: %s)\n", ip);
+		session[sd->fd]->func_parse = parse_admin;
+		result = true;
+	}
+
+	return result;
+}
 
 //---------------------------------------
 // Packet parsing for administation login
+//
+// List of supported operations:
+// 0x7530 - request server version (response: 0x7531)
+// 0x7938 - request server list (response: 0x7939)
+// 0x7920 - request entire list of accounts (response: 0x7921)
+// 0x794e - request message broadcast (response: 0x794f + 0x2726)
+
+// 0x7930 - request account creation (response: 0x7931)
+// 0x7932 - request account deletion (response: 0x7933 + 0x2730)
+
+// 0x7934 - request account password modification (response: 0x7935)
+// 0x7936 - request account state modification (response: 0x7937 + 0x2731)
+// 0x793a - request password check (response: 0x793b)
+// 0x793c - request account sex modification (response: 0x793d + 0x2723)
+// 0x793e - request account gm-level modification (response: 0x793f)
+// 0x7940 - request account email modification (response: 0x7941)
+// 0x7942 - request account memo modification (response: 0x7943)
+// 0x7948 - request account expiration-time modification - absolute (response: 0x7949)
+// 0x7950 - request account expiration-time modification - relative (response: 0x7951)
+// 0x794a - request account unban-time modification - absolute (response: 0x794b + 0x2731)
+// 0x794c - request account unban-time modification - relative (response: 0x794d + 0x2731)
+
+// 0x7944 - request account id lookup by name (response: 0x7945)
+// 0x7946 - request account name lookup by id (response: 0x7947)
+// 0x7952 - request account information lookup by name (response: 0x7953)
+// 0x7954 - request account information lookup by id (response: 0x7953)
 //---------------------------------------
 int parse_admin(int fd)
 {
 	unsigned int i, j;
 	char* account_name;
+	struct mmo_account acc;
 
 	uint32 ipl = session[fd]->client_addr;
 	char ip[16];
@@ -75,7 +120,7 @@ int parse_admin(int fd)
 			WFIFOSET(fd,10);
 			RFIFOSKIP(fd,2);
 			break;
-
+/*
 		case 0x7920:	// Request of an accounts list
 			if (RFIFOREST(fd) < 10)
 				return 0;
@@ -130,158 +175,145 @@ int parse_admin(int fd)
 				DELETE_BUFFER(id);
 			}
 			break;
-
+*/
 		case 0x7930:	// Request for an account creation
 			if (RFIFOREST(fd) < 91)
 				return 0;
-			{
-				struct mmo_account ma;
-				safestrncpy(ma.userid, (char*)RFIFOP(fd, 2), NAME_LENGTH);
-				safestrncpy(ma.pass,   (char*)RFIFOP(fd,26), NAME_LENGTH);
-				safestrncpy(ma.email,  (char*)RFIFOP(fd,51), 40);
-				memcpy(ma.lastlogin, "-", 2);
-				ma.sex = RFIFOB(fd,50);
-				RFIFOSKIP(fd,91);
-
-				WFIFOW(fd,0) = 0x7931;
-				WFIFOL(fd,2) = 0xffffffff; // invalid account id
-				safestrncpy((char*)WFIFOP(fd,6), ma.userid, 24);
-				if (strlen(ma.userid) < 4 || strlen(ma.pass) < 4) {
-					ShowNotice("'ladmin': Attempt to create an invalid account (account or pass is too short, ip: %s)\n", ip);
-				} else if (ma.sex != 'F' && ma.sex != 'M') {
-					ShowNotice("'ladmin': Attempt to create an invalid account (account: %s, received pass: %s, invalid sex, ip: %s)\n", ma.userid, ma.pass, ip);
-				} else if (account_id_count > END_ACCOUNT_NUM) {
-					ShowNotice("'ladmin': Attempt to create an account, but there is no more available id number (account: %s, pass: %s, sex: %c, ip: %s)\n", ma.userid, ma.pass, ma.sex, ip);
-				} else {
-					remove_control_chars(ma.userid);
-					remove_control_chars(ma.pass);
-					remove_control_chars(ma.email);
-					ARR_FIND( 0, auth_num, i, strncmp(auth_dat[i].userid, ma.userid, 24) == 0 );
-					if( i < auth_num )
-						ShowNotice("'ladmin': Attempt to create an already existing account (account: %s, pass: %s, received pass: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ma.pass, ip);
-					else
-					{
-						int new_id;
-						new_id = mmo_auth_new(&ma);
-						ShowNotice("'ladmin': Account creation (account: %s (id: %d), pass: %s, sex: %c, email: %s, ip: %s)\n", ma.userid, new_id, ma.pass, ma.sex, auth_dat[i].email, ip);
-						WFIFOL(fd,2) = new_id;
-						mmo_auth_sync();
-					}
-				}
-				WFIFOSET(fd,30);
-			}
+		{
+			struct mmo_account ma;
+			safestrncpy(ma.userid, (char*)RFIFOP(fd, 2), sizeof(ma.userid));
+			safestrncpy(ma.pass, (char*)RFIFOP(fd,26), sizeof(ma.pass));
+			ma.sex = RFIFOB(fd,50);
+			safestrncpy(ma.email, (char*)RFIFOP(fd,51), sizeof(ma.email));
+			safestrncpy(ma.lastlogin, "-", sizeof(ma.lastlogin));
+
+			ShowNotice("'ladmin': Account creation request (account: %s pass: %s, sex: %c, email: %s, ip: %s)\n", ma.userid, ma.pass, ma.sex, ma.email, ip);
+
+			WFIFOW(fd,0) = 0x7931;
+			WFIFOL(fd,2) = mmo_auth_new(ma.userid, ma.pass, ma.sex, ip);
+			safestrncpy((char*)WFIFOP(fd,6), ma.userid, 24);
+			WFIFOSET(fd,30);
+		}
+			RFIFOSKIP(fd,91);
 			break;
-
+/*
 		case 0x7932:	// Request for an account deletion
 			if (RFIFOREST(fd) < 26)
 				return 0;
-			WFIFOW(fd,0) = 0x7933;
-			WFIFOL(fd,2) = 0xFFFFFFFF;
-			account_name = (char*)RFIFOP(fd,2);
+		{
+			struct mmo_account acc;
+
+			char* account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
+
+			WFIFOW(fd,0) = 0x7933;
+
+			if( accounts->load_str(accounts, &acc, account_name) )
+			{
 				// Char-server is notified of deletion (for characters deletion).
 				unsigned char buf[65535];
 				WBUFW(buf,0) = 0x2730;
-				WBUFL(buf,2) = auth_dat[i].account_id;
+				WBUFL(buf,2) = acc.account_id;
 				charif_sendallwos(-1, buf, 6);
+
 				// send answer
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				// save deleted account in log file
-				ShowNotice("'ladmin': Account deletion (account: %s, id: %d, ip: %s) - saved in next line:\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
-				mmo_auth_tostr((char*)buf, &auth_dat[i]);
-				ShowNotice("%s\n", buf);
+				memcpy(WFIFOP(fd,6), acc.userid, 24);
+				WFIFOL(fd,2) = acc.account_id;
+
 				// delete account
-				memset(auth_dat[i].userid, '\0', sizeof(auth_dat[i].userid));
+				memset(acc.userid, '\0', sizeof(acc.userid));
 				auth_dat[i].account_id = -1;
 				mmo_auth_sync();
 			} else {
+				WFIFOL(fd,2) = -1;
 				memcpy(WFIFOP(fd,6), account_name, 24);
 				ShowNotice("'ladmin': Attempt to delete an unknown account (account: %s, ip: %s)\n", account_name, ip);
 			}
 			WFIFOSET(fd,30);
+		}
 			RFIFOSKIP(fd,26);
 			break;
-
+*/
 		case 0x7934:	// Request to change a password
 			if (RFIFOREST(fd) < 50)
 				return 0;
-			WFIFOW(fd,0) = 0x7935;
-			WFIFOL(fd,2) = 0xFFFFFFFF; /// WTF??? an unsigned being set to a -1
-			account_name = (char*)RFIFOP(fd,2);
+		{
+			struct mmo_account acc;
+
+			char* account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
-				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-				memcpy(auth_dat[i].pass, RFIFOP(fd,26), 24);
-				auth_dat[i].pass[23] = '\0';
-				remove_control_chars(auth_dat[i].pass);
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				ShowNotice("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ip);
-				mmo_auth_sync();
-			} else {
-				memcpy(WFIFOP(fd,6), account_name, 24);
+
+			WFIFOW(fd,0) = 0x7935;
+
+			if( accounts->load_str(accounts, &acc, account_name) )
+			{
+				WFIFOL(fd,2) = acc.account_id;
+				safestrncpy((char*)WFIFOP(fd,6), acc.userid, 24);
+				safestrncpy(acc.pass, (char*)RFIFOP(fd,26), 24);
+				ShowNotice("'ladmin': Modification of a password (account: %s, new password: %s, ip: %s)\n", acc.userid, acc.pass, ip);
+
+				accounts->save(accounts, &acc);
+			}
+			else
+			{
+				WFIFOL(fd,2) = -1;
+				safestrncpy((char*)WFIFOP(fd,6), account_name, 24);
 				ShowNotice("'ladmin': Attempt to modify the password of an unknown account (account: %s, ip: %s)\n", account_name, ip);
 			}
+
 			WFIFOSET(fd,30);
+		}
 			RFIFOSKIP(fd,50);
 			break;
 
 		case 0x7936:	// Request to modify a state
 			if (RFIFOREST(fd) < 50)
 				return 0;
+		{
+			struct mmo_account acc;
+
+			char* account_name = (char*)RFIFOP(fd,2);
+			uint32 state = RFIFOL(fd,26);
+			account_name[23] = '\0';
+
+			WFIFOW(fd,0) = 0x7937;
+
+			if( accounts->load_str(accounts, &acc, account_name) )
 			{
-				char error_message[20];
-				uint32 statut;
-				WFIFOW(fd,0) = 0x7937;
-				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-				account_name = (char*)RFIFOP(fd,2);
-				account_name[23] = '\0';
-				remove_control_chars(account_name);
-				statut = RFIFOL(fd,26);
-				memcpy(error_message, RFIFOP(fd,30), 20);
-				error_message[19] = '\0';
-				remove_control_chars(error_message);
-				if (statut != 7 || error_message[0] == '\0') { // 7: // 6 = Your are Prohibited to log in until %s
-					strcpy(error_message, "-");
-				}
-				i = search_account_index(account_name);
-				if (i != -1) {
-					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					if (auth_dat[i].state == statut && strcmp(auth_dat[i].error_message, error_message) == 0)
-						ShowNotice("'ladmin': Modification of a state, but the state of the account is already the good state (account: %s, received state: %d, ip: %s)\n", account_name, statut, ip);
-					else {
-						if (statut == 7)
-							ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d - prohibited to login until '%s', ip: %s)\n", auth_dat[i].userid, statut, error_message, ip);
-						else
-							ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", auth_dat[i].userid, statut, ip);
-						if (auth_dat[i].state == 0) {
-							unsigned char buf[16];
-							WBUFW(buf,0) = 0x2731;
-							WBUFL(buf,2) = auth_dat[i].account_id;
-							WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
-							WBUFL(buf,7) = statut; // status or final date of a banishment
-							charif_sendallwos(-1, buf, 11);
-						}
-						auth_dat[i].state = statut;
-						memcpy(auth_dat[i].error_message, error_message, 20);
-						mmo_auth_sync();
+				memcpy(WFIFOP(fd,6), acc.userid, 24);
+				WFIFOL(fd,2) = acc.account_id;
+
+				if (acc.state == state)
+					ShowNotice("'ladmin': Modification of a state, but the state of the account already has this value (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
+				else
+				{
+					ShowNotice("'ladmin': Modification of a state (account: %s, new state: %d, ip: %s)\n", acc.userid, state, ip);
+
+					if (acc.state == 0) {
+						unsigned char buf[16];
+						WBUFW(buf,0) = 0x2731;
+						WBUFL(buf,2) = acc.account_id;
+						WBUFB(buf,6) = 0; // 0: change of statut, 1: ban
+						WBUFL(buf,7) = state; // status or final date of a banishment
+						charif_sendallwos(-1, buf, 11);
 					}
-				} else {
-					memcpy(WFIFOP(fd,6), account_name, 24);
-					ShowNotice("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", account_name, statut, ip);
+					acc.state = state;
+					accounts->save(accounts, &acc);
 				}
-				WFIFOL(fd,30) = statut;
 			}
+			else
+			{
+				ShowNotice("'ladmin': Attempt to modify the state of an unknown account (account: %s, received state: %d, ip: %s)\n", account_name, state, ip);
+				WFIFOL(fd,2) = -1;
+				memcpy(WFIFOP(fd,6), account_name, 24);
+			}
+
+			WFIFOL(fd,30) = state;
 			WFIFOSET(fd,34);
+		}
 			RFIFOSKIP(fd,50);
 			break;
-
+/*
 		case 0x7938:	// Request for servers list and # of online players
 		{		
 			uint8 server_num = 0;
@@ -312,18 +344,18 @@ int parse_admin(int fd)
 			account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
 			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
+			if( accounts->load_str(accounts, &acc, account_name) )
+			{
 				char pass[25];
 				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
 				memcpy(pass, RFIFOP(fd,26), 24);
 				pass[24] = '\0';
 				remove_control_chars(pass);
-				if (strcmp(auth_dat[i].pass, pass) == 0) {
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					ShowNotice("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", auth_dat[i].userid, auth_dat[i].pass, ip);
+				if (strcmp(acc.pass, pass) == 0) {
+					WFIFOL(fd,2) = acc.account_id;
+					ShowNotice("'ladmin': Check of password OK (account: %s, password: %s, ip: %s)\n", acc.userid, acc.pass, ip);
 				} else {
-					ShowNotice("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", auth_dat[i].userid, pass, ip);
+					ShowNotice("'ladmin': Failure of password check (account: %s, proposed pass: %s, ip: %s)\n", acc.userid, pass, ip);
 				}
 			} else {
 				memcpy(WFIFOP(fd,6), account_name, 24);
@@ -337,7 +369,7 @@ int parse_admin(int fd)
 			if (RFIFOREST(fd) < 27)
 				return 0;
 			WFIFOW(fd,0) = 0x793d;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
+			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
 			account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
 			remove_control_chars(account_name);
@@ -351,22 +383,25 @@ int parse_admin(int fd)
 					else
 						ShowNotice("'ladmin': Attempt to give an invalid sex (account: %s, received sex: 'control char', ip: %s)\n", account_name, ip);
 				} else {
-					i = search_account_index(account_name);
-					if (i != -1) {
-						memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-						if (auth_dat[i].sex != ((sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm'))) {
+					if( accounts->load_str(accounts, &acc, account_name) )
+					{
+						memcpy(WFIFOP(fd,6), acc.userid, 24);
+						if (acc.sex != sex)
+						{
 							unsigned char buf[16];
-							WFIFOL(fd,2) = auth_dat[i].account_id;
-							auth_dat[i].sex = (sex == 'S' || sex == 's') ? 2 : (sex == 'M' || sex == 'm');
-							ShowNotice("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", auth_dat[i].userid, sex, ip);
-							mmo_auth_sync();
+							ShowNotice("'ladmin': Modification of a sex (account: %s, new sex: %c, ip: %s)\n", acc.userid, sex, ip);
+
+							WFIFOL(fd,2) = acc.account_id;
+							acc.sex = sex;
+							accounts->save(accounts, &acc);
+
 							// send to all char-server the change
 							WBUFW(buf,0) = 0x2723;
-							WBUFL(buf,2) = auth_dat[i].account_id;
-							WBUFB(buf,6) = auth_dat[i].sex;
+							WBUFL(buf,2) = acc.account_id;
+							WBUFB(buf,6) = acc.sex;
 							charif_sendallwos(-1, buf, 7);
 						} else {
-							ShowNotice("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", auth_dat[i].userid, sex, ip);
+							ShowNotice("'ladmin': Modification of a sex, but the sex is already the good sex (account: %s, sex: %c, ip: %s)\n", acc.userid, sex, ip);
 						}
 					} else {
 						ShowNotice("'ladmin': Attempt to modify the sex of an unknown account (account: %s, received sex: %c, ip: %s)\n", account_name, sex, ip);
@@ -381,82 +416,31 @@ int parse_admin(int fd)
 			if (RFIFOREST(fd) < 27)
 				return 0;
 			WFIFOW(fd,0) = 0x793f;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
+			WFIFOL(fd,2) = 0xFFFFFFFF; // -1
 			account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
 			remove_control_chars(account_name);
 			memcpy(WFIFOP(fd,6), account_name, 24);
+		{
+			char new_gm_level;
+			new_gm_level = RFIFOB(fd,26);
+			if( new_gm_level < 0 || new_gm_level > 99 )
+				ShowNotice("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
+			else
+			if( !accounts->load_str(accounts, &acc, account_name) )
+				ShowNotice("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
+			else
 			{
-				char new_gm_level;
-				new_gm_level = RFIFOB(fd,26);
-				if (new_gm_level < 0 || new_gm_level > 99) {
-					ShowNotice("'ladmin': Attempt to give an invalid GM level (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
-				} else {
-					i = search_account_index(account_name);
-					if (i != -1) {
-						int acc = auth_dat[i].account_id;
-						memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-						if (isGM(acc) != new_gm_level) {
-							// modification of the file
-							FILE *fp, *fp2;
-							int lock;
-							char line[512];
-							int GM_account, GM_level;
-							int modify_flag;
-							char tmpstr[24];
-							time_t raw_time;
-							if ((fp2 = lock_fopen(GM_account_filename, &lock)) != NULL) {
-								if ((fp = fopen(GM_account_filename, "r")) != NULL) {
-									time(&raw_time);
-									strftime(tmpstr, 23, login_config.date_format, localtime(&raw_time));
-									modify_flag = 0;
-									// read/write GM file
-									while(fgets(line, sizeof(line), fp))
-									{
-										while(line[0] != '\0' && (line[strlen(line)-1] == '\n' || line[strlen(line)-1] == '\r'))
-											line[strlen(line)-1] = '\0'; // TODO: remove this
-										if ((line[0] == '/' && line[1] == '/') || line[0] == '\0')
-											fprintf(fp2, "%s\n", line);
-										else {
-											if (sscanf(line, "%d %d", &GM_account, &GM_level) != 2 && sscanf(line, "%d: %d", &GM_account, &GM_level) != 2)
-												fprintf(fp2, "%s\n", line);
-											else if (GM_account != acc)
-												fprintf(fp2, "%s\n", line);
-											else if (new_gm_level < 1) {
-												fprintf(fp2, "// %s: 'ladmin' GM level removed on account %d '%s' (previous level: %d)\n//%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
-												modify_flag = 1;
-											} else {
-												fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: %d)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, GM_level, acc, new_gm_level);
-												modify_flag = 1;
-											}
-										}
-									}
-									if (modify_flag == 0)
-										fprintf(fp2, "// %s: 'ladmin' GM level on account %d '%s' (previous level: 0)\n%d %d\n", tmpstr, acc, auth_dat[i].userid, acc, new_gm_level);
-									fclose(fp);
-								} else {
-									ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to read GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
-								}
-								if (lock_fclose(fp2, GM_account_filename, &lock) == 0) {
-									WFIFOL(fd,2) = acc;
-									ShowNotice("'ladmin': Modification of a GM level (account: %s (%d), new GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
-									// read and send new GM informations
-									read_gm_account();
-									send_GM_accounts(-1);
-								} else {
-									ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
-								}
-							} else {
-								ShowNotice("'ladmin': Attempt to modify of a GM level - impossible to write GM accounts file (account: %s (%d), received GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
-							}
-						} else {
-							ShowNotice("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", auth_dat[i].userid, acc, (int)new_gm_level, ip);
-						}
-					} else {
-						ShowNotice("'ladmin': Attempt to modify the GM level of an unknown account (account: %s, received GM level: %d, ip: %s)\n", account_name, (int)new_gm_level, ip);
-					}
+				memcpy(WFIFOP(fd,6), acc.userid, 24);
+
+				if (isGM(acc.account_id) == new_gm_level)
+					ShowNotice("'ladmin': Attempt to modify of a GM level, but the GM level is already the good GM level (account: %s (%d), GM level: %d, ip: %s)\n", acc.userid, acc.account_id, (int)new_gm_level, ip);
+				else
+				{
+					//TODO: change level
 				}
 			}
+		}
 			WFIFOSET(fd,30);
 			RFIFOSKIP(fd,27);
 			break;
@@ -739,133 +723,131 @@ int parse_admin(int fd)
 		case 0x7950:	// Request to change the validity limite (timestamp) (relative change)
 			if (RFIFOREST(fd) < 38)
 				return 0;
-			{
-				time_t timestamp;
-				struct tm *tmtime;
-				char tmpstr[2048];
-				char tmpstr2[2048];
-				WFIFOW(fd,0) = 0x7951;
-				WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
-				account_name = (char*)RFIFOP(fd,2);
-				account_name[23] = '\0';
-				remove_control_chars(account_name);
-				i = search_account_index(account_name);
-				if (i != -1) {
-					WFIFOL(fd,2) = auth_dat[i].account_id;
-					memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
-					timestamp = auth_dat[i].expiration_time;
-					if (timestamp == 0 || timestamp < time(NULL))
-						timestamp = time(NULL);
-					tmtime = localtime(&timestamp);
-					tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
-					tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
-					tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
-					tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
-					tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
-					tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
-					timestamp = mktime(tmtime);
-					if (timestamp != -1) {
-						strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
-						strftime(tmpstr2, 24, login_config.date_format, localtime(&timestamp));
-						ShowNotice("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
-						auth_dat[i].expiration_time = timestamp;
-						mmo_auth_sync();
-						WFIFOL(fd,30) = (unsigned long)auth_dat[i].expiration_time;
-					} else {
-						strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
-						ShowNotice("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
-						WFIFOL(fd,30) = 0;
-					}
+		{
+			time_t timestamp;
+			struct tm *tmtime;
+			char tmpstr[2048];
+			char tmpstr2[2048];
+			WFIFOW(fd,0) = 0x7951;
+			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
+			account_name = (char*)RFIFOP(fd,2);
+			account_name[23] = '\0';
+			remove_control_chars(account_name);
+			i = search_account_index(account_name);
+			if (i != -1) {
+				WFIFOL(fd,2) = auth_dat[i].account_id;
+				memcpy(WFIFOP(fd,6), auth_dat[i].userid, 24);
+				timestamp = auth_dat[i].expiration_time;
+				if (timestamp == 0 || timestamp < time(NULL))
+					timestamp = time(NULL);
+				tmtime = localtime(&timestamp);
+				tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,26);
+				tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,28);
+				tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,30);
+				tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,32);
+				tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,34);
+				tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,36);
+				timestamp = mktime(tmtime);
+				if (timestamp != -1) {
+					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
+					strftime(tmpstr2, 24, login_config.date_format, localtime(&timestamp));
+					ShowNotice("'ladmin': Adjustment of a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> new validity: %d (%s), ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), timestamp, (timestamp == 0 ? "unlimited" : tmpstr2), ip);
+					auth_dat[i].expiration_time = timestamp;
+					mmo_auth_sync();
+					WFIFOL(fd,30) = (unsigned long)auth_dat[i].expiration_time;
 				} else {
-					memcpy(WFIFOP(fd,6), account_name, 24);
-					ShowNotice("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", account_name, ip);
+					strftime(tmpstr, 24, login_config.date_format, localtime(&auth_dat[i].expiration_time));
+					ShowNotice("'ladmin': Impossible to adjust a validity limit (account: %s, %d (%s) + (%+d y %+d m %+d d %+d h %+d mn %+d s) -> ???, ip: %s)\n", auth_dat[i].userid, auth_dat[i].expiration_time, (auth_dat[i].expiration_time == 0 ? "unlimited" : tmpstr), (short)RFIFOW(fd,26), (short)RFIFOW(fd,28), (short)RFIFOW(fd,30), (short)RFIFOW(fd,32), (short)RFIFOW(fd,34), (short)RFIFOW(fd,36), ip);
 					WFIFOL(fd,30) = 0;
 				}
+			} else {
+				memcpy(WFIFOP(fd,6), account_name, 24);
+				ShowNotice("'ladmin': Attempt to adjust the validity limit of an unknown account (account: %s, ip: %s)\n", account_name, ip);
+				WFIFOL(fd,30) = 0;
 			}
+
 			WFIFOSET(fd,34);
+		}
 			RFIFOSKIP(fd,38);
 			break;
-
+*/
 		case 0x7952:	// Request about informations of an account (by account name)
 			if (RFIFOREST(fd) < 26)
 				return 0;
+		{
+			struct mmo_account acc;
+
 			WFIFOW(fd,0) = 0x7953;
-			WFIFOL(fd,2) = 0xFFFFFFFF; // WTF???
+
 			account_name = (char*)RFIFOP(fd,2);
 			account_name[23] = '\0';
-			remove_control_chars(account_name);
-			i = search_account_index(account_name);
-			if (i != -1) {
-				WFIFOL(fd,2) = auth_dat[i].account_id;
-				WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
-				memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
-				WFIFOB(fd,31) = auth_dat[i].sex;
-				WFIFOL(fd,32) = auth_dat[i].logincount;
-				WFIFOL(fd,36) = auth_dat[i].state;
-				memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
-				memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
-				memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
-				memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
-				WFIFOL(fd,140) = (unsigned long)auth_dat[i].expiration_time;
-				WFIFOL(fd,144) = (unsigned long)auth_dat[i].unban_time;
-				WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo);
-				if (auth_dat[i].memo[0]) {
-					memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
-				}
-				ShowNotice("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, auth_dat[i].account_id, ip);
-				WFIFOSET(fd,150+strlen(auth_dat[i].memo));
-			} else {
-				memcpy(WFIFOP(fd,7), account_name, 24);
-				WFIFOW(fd,148) = 0;
+
+			if( accounts->load_str(accounts, &acc, account_name) )
+			{
+				ShowNotice("'ladmin': Sending information of an account (request by the name; account: %s, id: %d, ip: %s)\n", acc.userid, acc.account_id, ip);
+				WFIFOL(fd,2) = acc.account_id;
+				WFIFOB(fd,6) = acc.level;
+				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
+				WFIFOB(fd,31) = acc.sex;
+				WFIFOL(fd,32) = acc.logincount;
+				WFIFOL(fd,36) = acc.state;
+				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
+				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
+				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
+				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
+				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
+				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
+				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
+			}
+			else
+			{
 				ShowNotice("'ladmin': Attempt to obtain information (by the name) of an unknown account (account: %s, ip: %s)\n", account_name, ip);
-				WFIFOSET(fd,150);
+				WFIFOL(fd,2) = -1;
+				safestrncpy((char*)WFIFOP(fd,7), account_name, 24); // not found
 			}
+
+			WFIFOSET(fd,150);
+		}
 			RFIFOSKIP(fd,26);
 			break;
 
 		case 0x7954:	// Request about information of an account (by account id)
 			if (RFIFOREST(fd) < 6)
 				return 0;
+		{
+			struct mmo_account acc;
+
+			int account_id = RFIFOL(fd,2);
+
+			WFIFOHEAD(fd,150);
 			WFIFOW(fd,0) = 0x7953;
-			WFIFOL(fd,2) = RFIFOL(fd,2);
-			memset(WFIFOP(fd,7), '\0', 24);
-			for(i = 0; i < auth_num; i++) {
-				if (auth_dat[i].account_id == (int)RFIFOL(fd,2)) {
-					ShowNotice("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", auth_dat[i].userid, RFIFOL(fd,2), ip);
-					WFIFOB(fd,6) = (unsigned char)isGM(auth_dat[i].account_id);
-					memcpy(WFIFOP(fd,7), auth_dat[i].userid, 24);
-					WFIFOB(fd,31) = auth_dat[i].sex;
-					WFIFOL(fd,32) = auth_dat[i].logincount;
-					WFIFOL(fd,36) = auth_dat[i].state;
-					memcpy(WFIFOP(fd,40), auth_dat[i].error_message, 20);
-					memcpy(WFIFOP(fd,60), auth_dat[i].lastlogin, 24);
-					memcpy(WFIFOP(fd,84), auth_dat[i].last_ip, 16);
-					memcpy(WFIFOP(fd,100), auth_dat[i].email, 40);
-					WFIFOL(fd,140) = (unsigned long)auth_dat[i].expiration_time;
-					WFIFOL(fd,144) = (unsigned long)auth_dat[i].unban_time;
-					WFIFOW(fd,148) = (uint16)strlen(auth_dat[i].memo);
-					if (auth_dat[i].memo[0]) {
-						memcpy(WFIFOP(fd,150), auth_dat[i].memo, strlen(auth_dat[i].memo));
-					}
-					WFIFOSET(fd,150+strlen(auth_dat[i].memo));
-					break;
-				}
+			WFIFOL(fd,2) = account_id;
+
+			if( accounts->load_num(accounts, &acc, account_id) )
+			{
+				ShowNotice("'ladmin': Sending information of an account (request by the id; account: %s, id: %d, ip: %s)\n", acc.userid, account_id, ip);
+				WFIFOB(fd,6) = acc.level;
+				safestrncpy((char*)WFIFOP(fd,7), acc.userid, 24);
+				WFIFOB(fd,31) = acc.sex;
+				WFIFOL(fd,32) = acc.logincount;
+				WFIFOL(fd,36) = acc.state;
+				safestrncpy((char*)WFIFOP(fd,40), "-", 20); // error message (removed)
+				safestrncpy((char*)WFIFOP(fd,60), acc.lastlogin, 24);
+				safestrncpy((char*)WFIFOP(fd,84), acc.last_ip, 16);
+				safestrncpy((char*)WFIFOP(fd,100), acc.email, 40);
+				WFIFOL(fd,140) = (unsigned long)acc.expiration_time;
+				WFIFOL(fd,144) = (unsigned long)acc.unban_time;
+				WFIFOW(fd,148) = 0; // previously, this was strlen(memo), and memo went afterwards
 			}
-			if (i == auth_num) {
-				ShowNotice("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", RFIFOL(fd,2), ip);
-				strncpy((char*)WFIFOP(fd,7), "", 24);
-				WFIFOW(fd,148) = 0;
-				WFIFOSET(fd,150);
+			else
+			{
+				ShowNotice("'ladmin': Attempt to obtain information (by the id) of an unknown account (id: %d, ip: %s)\n", account_id, ip);
+				safestrncpy((char*)WFIFOP(fd,7), "", 24); // not found
 			}
-			RFIFOSKIP(fd,6);
-			break;
 
-		case 0x7955:	// Request to reload GM file (no answer)
-			ShowStatus("'ladmin': Request to re-load GM configuration file (ip: %s).\n", ip);
-			read_gm_account();
-			// send GM accounts to all char-servers
-			send_GM_accounts(-1);
-			RFIFOSKIP(fd,2);
+			WFIFOSET(fd,150);
+		}
+			RFIFOSKIP(fd,6);
 			break;
 
 		default:

+ 25 - 0
src/login/ipban.h

@@ -0,0 +1,25 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef __IPBAN_H_INCLUDED__
+#define __IPBAN_H_INCLUDED__
+
+#include "../common/cbasetypes.h"
+
+// initialize
+void ipban_init(void);
+
+// finalize
+void ipban_final(void);
+
+// check ip against ban list
+bool ipban_check(uint32 ip);
+
+// increases failure count for the specified IP
+void ipban_log(uint32 ip);
+
+// parses configuration option
+bool ipban_config_read(const char* key, const char* value);
+
+
+#endif // __IPBAN_H_INCLUDED__

+ 209 - 0
src/login/ipban_sql.c

@@ -0,0 +1,209 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/db.h"
+#include "../common/malloc.h"
+#include "../common/sql.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "login.h"
+#include "ipban.h"
+#include <stdlib.h>
+#include <string.h>
+
+// database options
+static char   ipban_db_hostname[32] = "127.0.0.1";
+static uint16 ipban_db_port = 3306;
+static char   ipban_db_username[32] = "ragnarok";
+static char   ipban_db_password[32] = "ragnarok";
+static char   ipban_db_database[32] = "ragnarok";
+static char   ipban_table[32] = "ipbanlist";
+
+static char   log_db_hostname[32] = "127.0.0.1";
+static uint16 log_db_port = 3306;
+static char   log_db_username[32] = "ragnarok";
+static char   log_db_password[32] = "ragnarok";
+static char   log_db_database[32] = "ragnarok";
+static char   loginlog_table[32] = "loginlog";
+
+static char default_codepage[32] = "";
+
+// globals
+static Sql* sql_handle;
+static Sql* logsql_handle;
+static int cleanup_timer_id = INVALID_TIMER;
+
+int ipban_cleanup(int tid, unsigned int tick, int id, intptr data);
+
+
+// initialize
+void ipban_init(void)
+{
+	// establish connections
+	sql_handle = Sql_Malloc();
+	if( SQL_ERROR == Sql_Connect(sql_handle, ipban_db_username, ipban_db_password, ipban_db_hostname, ipban_db_port, ipban_db_database) )
+	{
+		Sql_ShowDebug(sql_handle);
+		Sql_Free(sql_handle);
+		exit(EXIT_FAILURE);
+	}
+	if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) )
+		Sql_ShowDebug(sql_handle);
+
+	logsql_handle = Sql_Malloc();
+	if( SQL_ERROR == Sql_Connect(logsql_handle, log_db_username, log_db_password, log_db_hostname, log_db_port, log_db_database) )
+	{
+		Sql_ShowDebug(logsql_handle);
+		Sql_Free(logsql_handle);
+		exit(EXIT_FAILURE);
+	}
+	if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(logsql_handle, default_codepage) )
+		Sql_ShowDebug(logsql_handle);
+
+	// set up periodic cleanup of connection history and active bans
+	add_timer_func_list(ipban_cleanup, "ipban_cleanup");
+	cleanup_timer_id = add_timer_interval(gettick()+10, ipban_cleanup, 0, 0, 60*1000);
+}
+
+// finalize
+void ipban_final(void)
+{
+	// release data
+	delete_timer(cleanup_timer_id, ipban_cleanup);
+
+	// close connections
+	Sql_Free(sql_handle);
+	sql_handle = NULL;
+	Sql_Free(logsql_handle);
+	logsql_handle = NULL;
+}
+
+// load configuration options
+bool ipban_config_read(const char* key, const char* value)
+{
+	// login server settings
+	if( strcmpi(key, "ipban.enable") == 0 )
+		login_config.ipban = (bool)config_switch(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban") == 0 )
+		login_config.dynamic_pass_failure_ban = (bool)config_switch(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_interval") == 0 )
+		login_config.dynamic_pass_failure_ban_interval = atoi(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_limit") == 0 )
+		login_config.dynamic_pass_failure_ban_limit = atoi(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_duration") == 0 )
+		login_config.dynamic_pass_failure_ban_duration = atoi(value);
+	else
+
+	// ipban table settings
+	if( strcmpi(key, "ipban.sql.db_hostname") == 0 )
+		safestrncpy(ipban_db_hostname, value, sizeof(ipban_db_hostname));
+	else
+	if( strcmpi(key, "ipban.sql.db_port") == 0 )
+		ipban_db_port = (uint16)strtoul(value, NULL, 10);
+	else
+	if( strcmpi(key, "ipban.sql.db_username") == 0 )
+		safestrncpy(ipban_db_username, value, sizeof(ipban_db_username));
+	else
+	if( strcmpi(key, "ipban.sql.db_password") == 0 )
+		safestrncpy(ipban_db_password, value, sizeof(ipban_db_password));
+	else
+	if( strcmpi(key, "ipban.sql.db_database") == 0 )
+		safestrncpy(ipban_db_database, value, sizeof(ipban_db_database));
+	else
+	if( strcmpi(key, "ipban.sql.ipban_table") == 0 )
+		safestrncpy(ipban_table, value, sizeof(ipban_table));
+	else
+
+	// interserver settings
+	if( strcmpi(key, "log_db_ip") == 0 )
+		safestrncpy(log_db_hostname, value, sizeof(log_db_hostname));
+	else
+	if( strcmpi(key, "log_db_port") == 0 )
+		log_db_port = (uint16)strtoul(value, NULL, 10);
+	else
+	if( strcmpi(key, "log_db_id") == 0 )
+		safestrncpy(log_db_username, value, sizeof(log_db_username));
+	else
+	if( strcmpi(key, "log_db_pw") == 0 )
+		safestrncpy(log_db_password, value, sizeof(log_db_password));
+	else
+	if( strcmpi(key, "log_db") == 0 )
+		safestrncpy(log_db_database, value, sizeof(log_db_database));
+	else
+	if( strcmpi(key, "loginlog_db") == 0 )
+		safestrncpy(loginlog_table, value, sizeof(loginlog_table));
+	else
+	if( strcmpi(key, "default_codepage") == 0 )
+		safestrncpy(default_codepage, value, sizeof(default_codepage));
+	else
+		return false;
+
+	return true;
+}
+
+// check ip against active bans list
+bool ipban_check(uint32 ip)
+{
+	uint8* p = (uint8*)&ip;
+	char* data = NULL;
+	int matches;
+
+	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u'",
+		ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
+	{
+		Sql_ShowDebug(sql_handle);
+		// close connection because we can't verify their connectivity.
+		return true;
+	}
+
+	if( SQL_ERROR == Sql_NextRow(sql_handle) )
+		return true;// Shouldn't happen, but just in case...
+
+	Sql_GetData(sql_handle, 0, &data, NULL);
+	matches = atoi(data);
+	Sql_FreeResult(sql_handle);
+
+	return( matches > 0 );
+}
+
+// log failed attempt
+void ipban_log(uint32 ip)
+{
+	unsigned long failures = 0;
+	if( SQL_ERROR == Sql_Query(logsql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%s' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
+		loginlog_table, ip2str(ip,NULL), login_config.dynamic_pass_failure_ban_interval) )// how many times failed account? in one ip.
+		Sql_ShowDebug(sql_handle);
+
+	//check query result
+	if( SQL_SUCCESS == Sql_NextRow(logsql_handle) )
+	{
+		char* data;
+		Sql_GetData(logsql_handle, 0, &data, NULL);
+		failures = strtoul(data, NULL, 10);
+		Sql_FreeResult(logsql_handle);
+	}
+
+	// if over the limit, add a temporary ban entry
+	if( failures >= login_config.dynamic_pass_failure_ban_limit )
+	{
+		uint8* p = (uint8*)&ip;
+		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban')",
+			ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) )
+			Sql_ShowDebug(sql_handle);
+	}
+}
+
+// remove expired bans
+int ipban_cleanup(int tid, unsigned int tick, int id, intptr data)
+{
+	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
+		Sql_ShowDebug(sql_handle);
+
+	return 0;
+}

+ 50 - 0
src/login/ipban_txt.c

@@ -0,0 +1,50 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/strlib.h"
+#include "login.h"
+#include "ipban.h"
+#include <stdlib.h>
+#include <string.h>
+
+void ipban_init(void)
+{
+}
+
+void ipban_final(void)
+{
+}
+
+bool ipban_check(uint32 ip)
+{
+	return false;
+}
+
+void ipban_log(uint32 ip)
+{
+}
+
+bool ipban_config_read(const char* key, const char* value)
+{
+	// login server settings
+	if( strcmpi(key, "ipban.enable") == 0 )
+		login_config.ipban = (bool)config_switch(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban") == 0 )
+		login_config.dynamic_pass_failure_ban = (bool)config_switch(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_interval") == 0 )
+		login_config.dynamic_pass_failure_ban_interval = atoi(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_limit") == 0 )
+		login_config.dynamic_pass_failure_ban_limit = atoi(value);
+	else
+	if( strcmpi(key, "ipban.dynamic_pass_failure_ban_duration") == 0 )
+		login_config.dynamic_pass_failure_ban_duration = atoi(value);
+	else
+		return false;
+
+	return true;
+}
+

File diff suppressed because it is too large
+ 166 - 885
src/login/login.c


+ 15 - 28
src/login/login.h

@@ -7,6 +7,7 @@
 #include "../common/mmo.h" // NAME_LENGTH
 
 #define LOGIN_CONF_NAME "conf/login_athena.conf"
+#define INTER_CONF_NAME "conf/inter_athena.conf"
 #define LAN_CONF_NAME "conf/subnet_athena.conf"
 
 // supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both
@@ -38,9 +39,9 @@ struct mmo_char_server {
 	int fd;
 	uint32 ip;
 	uint16 port;
-	uint16 users;		// user count on this server
-	uint16 maintenance;	// in maintenance mode?
-	uint16 new_;		// allows creating new chars?
+	uint16 users;       // user count on this server
+	uint16 maintenance; // in maintenance mode?
+	uint16 new_;        // should display as 'new'?
 };
 
 struct Login_Config {
@@ -53,42 +54,28 @@ struct Login_Config {
 	bool console;                                   // console input system enabled?
 	bool new_account_flag;                          // autoregistration via _M/_F ?
 	int start_limited_time;                         // new account expiration time (-1: unlimited)
-//	bool case_sensitive;                            // are logins case sensitive ?
 	bool use_md5_passwds;                           // work with password hashes instead of plaintext passwords?
-//	bool login_gm_read;                             // should the login server handle info about gm accounts?
 	int min_level_to_connect;                       // minimum level of player/GM (0: player, 1-99: GM) to connect
 	bool online_check;                              // reject incoming players that are already registered as online ?
 	bool check_client_version;                      // check the clientversion set in the clientinfo ?
 	int client_version_to_connect;                  // the client version needed to connect (if checking is enabled)
 
-//	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
-//	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
-//	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures
-//	unsigned int dynamic_pass_failure_ban_limit;    // number of failures needed to trigger the ipban
-//	unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban
+	bool admin_state;                               // is ladmin support enabled?
+	char admin_pass[24];                            // security password for ladmin
+	char admin_allowed_host[32];                    // host/ip that is allowed to connect as ladmin
+
+	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
+	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
+	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures
+	unsigned int dynamic_pass_failure_ban_limit;    // number of failures needed to trigger the ipban
+	unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban
 	bool use_dnsbl;                                 // dns blacklist blocking ?
 	char dnsbl_servs[1024];                         // comma-separated list of dnsbl servers
 
+	char account_engine[256];                       // name of the engine to use (defaults to auto, for the first available engine)
 };
 
-struct mmo_account {
-
-	int account_id;
-	char sex;
-	char userid[24];
-	char pass[32+1]; // 23+1 for normal, 32+1 for md5-ed passwords
-	char lastlogin[24];
-	int logincount;
-	uint32 state; // packet 0x006a value + 1 (0: compte OK)
-	char email[40]; // e-mail (by default: a@a.com)
-	char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
-	time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-	char last_ip[16]; // save of last IP of connection
-	char memo[255]; // a memo field
-	int account_reg2_num;
-	struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
-};
+extern struct Login_Config login_config;
 
 
 #endif /* _LOGIN_H_ */

+ 14 - 0
src/login/loginlog.h

@@ -0,0 +1,14 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#ifndef __LOGINLOG_H_INCLUDED__
+#define __LOGINLOG_H_INCLUDED__
+
+
+void login_log(uint32 ip, const char* username, int rcode, const char* message);
+bool loginlog_init(void);
+bool loginlog_final(void);
+bool loginlog_config_read(const char* w1, const char* w2);
+
+
+#endif // __LOGINLOG_H_INCLUDED__

+ 93 - 0
src/login/loginlog_sql.c

@@ -0,0 +1,93 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/socket.h"
+#include "../common/sql.h"
+#include "../common/strlib.h"
+#include <string.h>
+#include <stdlib.h> // exit
+
+char   log_db_ip[32] = "127.0.0.1";
+uint16 log_db_port = 3306;
+char   log_db_id[32] = "ragnarok";
+char   log_db_pw[32] = "ragnarok";
+char   log_db_db[32] = "ragnarok";
+char   log_db[32] = "log";
+
+char loginlog_db[256] = "loginlog";
+Sql* sql_handle;
+bool enabled = false;
+
+
+/*=============================================
+ * Records an event in the login log
+ *---------------------------------------------*/
+void login_log(uint32 ip, const char* username, int rcode, const char* message)
+{
+	char esc_username[NAME_LENGTH*2+1];
+	char esc_message[255*2+1];
+	int retcode;
+
+	if( !enabled )
+		return;
+
+	Sql_EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH));
+	Sql_EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255));
+
+	retcode = Sql_Query(sql_handle,
+		"INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%s', '%s', '%d', '%s')",
+		loginlog_db, ip2str(ip,NULL), esc_username, rcode, message);
+
+	if( retcode != SQL_SUCCESS )
+		Sql_ShowDebug(sql_handle);
+}
+
+bool loginlog_init(void)
+{
+	sql_handle = Sql_Malloc();
+
+	if( SQL_ERROR == Sql_Connect(sql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) )
+	{
+		Sql_ShowDebug(sql_handle);
+		Sql_Free(sql_handle);
+		exit(EXIT_FAILURE);
+	}
+
+	enabled = true;
+
+	return true;
+}
+
+bool loginlog_final(void)
+{
+	Sql_Free(sql_handle);
+	sql_handle = NULL;
+	return true;
+}
+
+bool loginlog_config_read(const char* key, const char* value)
+{
+	if( strcmpi(key, "log_db_ip") == 0 )
+		safestrncpy(log_db_ip, value, sizeof(log_db_ip));
+	else
+	if( strcmpi(key, "log_db_port") == 0 )
+		log_db_port = (uint16)strtoul(value, NULL, 10);
+	else
+	if( strcmpi(key, "log_db_id") == 0 )
+		safestrncpy(log_db_id, value, sizeof(log_db_id));
+	else
+	if( strcmpi(key, "log_db_pw") == 0 )
+		safestrncpy(log_db_pw, value, sizeof(log_db_pw));
+	else
+	if( strcmpi(key, "log_db") == 0 )
+		safestrncpy(log_db, value, sizeof(log_db));
+	else
+	if( strcmpi(key, "loginlog_db") == 0 )
+		safestrncpy(loginlog_db, value, sizeof(loginlog_db));
+	else
+		return false;
+
+	return true;
+}

+ 74 - 0
src/login/loginlog_txt.c

@@ -0,0 +1,74 @@
+// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
+// For more information, see LICENCE in the main folder
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/core.h"
+#include "../common/malloc.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/showmsg.h"
+#include "account.h"
+#include "login.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char login_log_filename[1024] = "log/login.log";
+
+
+
+/*=============================================
+ * Records an event in the login log
+ *---------------------------------------------*/
+void login_log(uint32 ip, const char* username, int rcode, const char* message)
+{
+	FILE* log_fp;
+
+	if( !login_config.log_login )
+		return;
+	
+	log_fp = fopen(login_log_filename, "a");
+	if( log_fp != NULL )
+	{
+		char esc_username[NAME_LENGTH*4+1];
+		char esc_message[255*4+1];
+		time_t raw_time;
+		char str_time[24];
+
+		sv_escape_c(esc_username, username, NAME_LENGTH, NULL);
+		sv_escape_c(esc_message, message, 255, NULL);
+
+		time(&raw_time);
+		strftime(str_time, 24, login_config.date_format, localtime(&raw_time));
+		str_time[23] = '\0';
+
+		fprintf(log_fp, "%s\t%s\t%s\t%d\t%s\n", str_time, ip2str(ip,NULL), esc_username, rcode, esc_message);
+
+		fclose(log_fp);
+	}
+}
+
+
+bool loginlog_config_read(const char* w1, const char* w2)
+{
+	if(!strcmpi(w1, "login_log_filename"))
+		safestrncpy(login_log_filename, w2, sizeof(login_log_filename));
+	else
+		return false;
+
+	return true;
+}
+
+
+bool loginlog_init(void)
+{
+	return true;
+}
+
+
+bool loginlog_final(void)
+{
+	return true;
+}

+ 0 - 60
src/login_sql/Makefile.in

@@ -1,60 +0,0 @@
-
-COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_all/timer.o \
-	../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \
-	../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \
-	../common/obj_all/strlib.o ../common/obj_all/grfio.o ../common/obj_all/mapindex.o \
-	../common/obj_all/ers.o ../common/obj_all/md5calc.o ../common/obj_sql/sql.o 
-COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \
-	../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \
-	../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \
-	../common/grfio.h ../common/mapindex.h \
-	../common/ers.h ../common/md5calc.h ../common/sql.h 
-
-LOGIN_OBJ = obj_sql/login.o
-LOGIN_H = login.h
-
-HAVE_MYSQL=@HAVE_MYSQL@
-ifeq ($(HAVE_MYSQL),yes)
-	LOGIN_SERVER_SQL_DEPENDS=obj_sql $(LOGIN_OBJ) $(COMMON_OBJ)
-else
-	LOGIN_SERVER_SQL_DEPENDS=needs_mysql
-endif
-
-@SET_MAKE@
-
-#####################################################################
-.PHONY : all login-server_sql clean help
-
-all: login-server_sql
-
-login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS)
-	@CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_OBJ) $(COMMON_OBJ) @LIBS@ @MYSQL_LIBS@
-
-clean:
-	rm -rf *.o obj_sql ../../login-server_sql@EXEEXT@
-
-help:
-	@echo "possible targets are 'login-server_sql' 'all' 'clean' 'help'"
-	@echo "'login-server_sql'  - login server (SQL version)"
-	@echo "'all'               - builds all above targets"
-	@echo "'clean'             - cleans builds and objects"
-	@echo "'help'              - outputs this message"
-
-#####################################################################
-
-needs_mysql:
-	@echo "MySQL not found or disabled by the configure script"
-	@exit 1
-
-obj_sql:
-	-mkdir obj_sql
-
-obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H)
-	@CC@ @CFLAGS@ $(CUSTOM_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-
-# missing common object files
-../common/obj_all/%.o:
-	@$(MAKE) -C ../common sql
-
-../common/obj_sql/%.o:
-	@$(MAKE) -C ../common sql

+ 0 - 1982
src/login_sql/login.c

@@ -1,1982 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#include "../common/cbasetypes.h"
-#include "../common/mmo.h"
-#include "../common/core.h"
-#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/timer.h"
-#include "../common/malloc.h"
-#include "../common/strlib.h"
-#include "../common/showmsg.h"
-#include "../common/version.h"
-#include "../common/md5calc.h"
-#include "../common/sql.h"
-#include "login.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h> // for stat/lstat/fstat
-
-struct Login_Config login_config;
-
-int login_fd; // login server socket
-#define MAX_SERVERS 30
-struct mmo_char_server server[MAX_SERVERS]; // char server data
-
-#define sex_num2str(num) ( (num ==  0  ) ? 'F' : (num ==  1  ) ? 'M' : 'S' )
-#define sex_str2num(str) ( (str == 'F' ) ?  0  : (str == 'M' ) ?  1  :  2  )
-
-// Advanced subnet check [LuzZza]
-struct s_subnet {
-	uint32 mask;
-	uint32 char_ip;
-	uint32 map_ip;
-} subnet[16];
-
-int subnet_count = 0;
-
-// GM account management
-struct gm_account* gm_account_db = NULL;
-unsigned int GM_num = 0; // number of gm accounts
-
-//Account registration flood protection [Kevin]
-int allowed_regs = 1;
-int time_allowed = 10; //in seconds
-unsigned int new_reg_tick = 0;
-
-
-// data handling (SQL)
-Sql* sql_handle;
-
-// database parameters
-uint16 login_server_port = 3306;
-char login_server_ip[32] = "127.0.0.1";
-char login_server_id[32] = "ragnarok";
-char login_server_pw[32] = "ragnarok";
-char login_server_db[32] = "ragnarok";
-char default_codepage[32] = "";
-
-char login_db[256] = "login";
-char loginlog_db[256] = "loginlog";
-char reg_db[256] = "global_reg_value";
-
-// added to help out custom login tables, without having to recompile
-// source so options are kept in the login_athena.conf or the inter_athena.conf
-char login_db_account_id[256] = "account_id";
-char login_db_userid[256] = "userid";
-char login_db_user_pass[256] = "user_pass";
-char login_db_level[256] = "level";
-
-
-//-----------------------------------------------------
-// Auth database
-//-----------------------------------------------------
-#define AUTH_TIMEOUT 30000
-
-struct auth_node {
-	int account_id;
-	uint32 login_id1;
-	uint32 login_id2;
-	uint32 ip;
-	char sex;
-};
-
-static DBMap* auth_db; // int account_id -> struct auth_node*
-
-//-----------------------------------------------------
-// Online User Database [Wizputer]
-//-----------------------------------------------------
-
-struct online_login_data {
-	int account_id;
-	int waiting_disconnect;
-	int char_server;
-};
-
-static DBMap* online_db; // int account_id -> struct online_login_data*
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data);
-
-static void* create_online_user(DBKey key, va_list args)
-{
-	struct online_login_data* p;
-	CREATE(p, struct online_login_data, 1);
-	p->account_id = key.i;
-	p->char_server = -1;
-	p->waiting_disconnect = -1;
-	return p;
-}
-
-struct online_login_data* add_online_user(int char_server, int account_id)
-{
-	struct online_login_data* p;
-	if( !login_config.online_check )
-		return NULL;
-	p = (struct online_login_data*)idb_ensure(online_db, account_id, create_online_user);
-	p->char_server = char_server;
-	if( p->waiting_disconnect != -1 )
-	{
-		delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-		p->waiting_disconnect = -1;
-	}
-	return p;
-}
-
-void remove_online_user(int account_id)
-{
-	struct online_login_data* p;
-	if( !login_config.online_check )
-		return;
-	p = (struct online_login_data*)idb_get(online_db, account_id);
-	if( p == NULL )
-		return;
-	if( p->waiting_disconnect != -1 )
-		delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-
-	idb_remove(online_db, account_id);
-}
-
-static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr data)
-{
-	struct online_login_data* p = (struct online_login_data*)idb_get(online_db, id);
-	if( p != NULL && p->waiting_disconnect == tid && p->account_id == id )
-	{
-		p->waiting_disconnect = -1;
-		remove_online_user(id);
-		idb_remove(auth_db, id);
-	}
-	return 0;
-}
-
-//--------------------------------------------------------------------
-// Packet send to all char-servers, except one (wos: without our self)
-//--------------------------------------------------------------------
-int charif_sendallwos(int sfd, uint8* buf, size_t len)
-{
-	int i, c;
-
-	for( i = 0, c = 0; i < MAX_SERVERS; ++i )
-	{
-		int fd = server[i].fd;
-		if( session_isValid(fd) && fd != sfd )
-		{
-			WFIFOHEAD(fd,len);
-			memcpy(WFIFOP(fd,0), buf, len);
-			WFIFOSET(fd,len);
-			++c;
-		}
-	}
-
-	return c;
-}
-
-//-----------------------------------------------------
-// Read GM accounts
-//-----------------------------------------------------
-void read_gm_account(void)
-{
-	if( !login_config.login_gm_read )
-		return;// char server's job
-
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `%s`,`%s` FROM `%s` WHERE `%s` > '0'", login_db_account_id, login_db_level, login_db, login_db_level) )
-	{
-		Sql_ShowDebug(sql_handle);
-		return;// Failed to read GM list!
-	}
-
-	RECREATE(gm_account_db, struct gm_account, (size_t)Sql_NumRows(sql_handle));
-
-	for( GM_num = 0; SQL_SUCCESS == Sql_NextRow(sql_handle); ++GM_num )
-	{
-		char* account;
-		char* level;
-
-		Sql_GetData(sql_handle, 0, &account, NULL);
-		Sql_GetData(sql_handle, 1, &level, NULL);
-
-		gm_account_db[GM_num].account_id = atoi(account);
-		gm_account_db[GM_num].level = atoi(level);
-	}
-
-	Sql_FreeResult(sql_handle);
-}
-
-//-----------------------------------------------------
-// Send GM accounts to one or all char-servers
-//-----------------------------------------------------
-void send_GM_accounts(int fd)
-{
-	unsigned int i;
-	uint8 buf[32767];
-	uint16 len;
-
-	if( !login_config.login_gm_read )
-		return;
-
-	len = 4;
-	WBUFW(buf,0) = 0x2732;
-	for( i = 0; i < GM_num; ++i )
-	{
-		// send only existing accounts. We can not create a GM account when server is online.
-		if( gm_account_db[i].level > 0 )
-		{
-			WBUFL(buf,len) = gm_account_db[i].account_id;
-			WBUFB(buf,len+4) = (uint8)gm_account_db[i].level;
-			len += 5;
-			if( len >= 32000 )
-			{
-				ShowWarning("send_GM_accounts: Too many accounts! Only %d out of %d were sent.\n", i, GM_num);
-				break;
-			}
-		}
-	}
-
-	WBUFW(buf,2) = len;
-	if( fd == -1 )// send to all charservers
-		charif_sendallwos(-1, buf, len);
-	else
-	{// send only to target
-		WFIFOHEAD(fd,len);
-		memcpy(WFIFOP(fd,0), buf, len);
-		WFIFOSET(fd,len);
-	}
-
-	return;
-}
-
-/*=============================================
- * Does a mysql_ping to all connection handles
- *---------------------------------------------*/
-int login_sql_ping(int tid, unsigned int tick, int id, intptr data) 
-{
-	ShowInfo("Pinging SQL server to keep connection alive...\n");
-	Sql_Ping(sql_handle);
-	return 0;
-}
-
-int sql_ping_init(void)
-{
-	uint32 connection_timeout, connection_ping_interval;
-
-	// set a default value first
-	connection_timeout = 28800; // 8 hours
-
-	// ask the mysql server for the timeout value
-	if( SQL_SUCCESS == Sql_GetTimeout(sql_handle, &connection_timeout) && connection_timeout < 60 )
-		connection_timeout = 60;
-
-	// establish keepalive
-	connection_ping_interval = connection_timeout - 30; // 30-second reserve
-	add_timer_func_list(login_sql_ping, "login_sql_ping");
-	add_timer_interval(gettick() + connection_ping_interval*1000, login_sql_ping, 0, 0, connection_ping_interval*1000);
-
-	return 0;
-}
-
-//-----------------------------------------------------
-// Read Account database - mysql db
-//-----------------------------------------------------
-int mmo_auth_sqldb_init(void)
-{
-	ShowStatus("Login server init....\n");
-
-	sql_handle = Sql_Malloc();
-
-	// DB connection start
-	ShowStatus("Connect Login Database Server....\n");
-	if( SQL_ERROR == Sql_Connect(sql_handle, login_server_id, login_server_pw, login_server_ip, login_server_port, login_server_db) )
-	{
-		Sql_ShowDebug(sql_handle);
-		Sql_Free(sql_handle);
-		exit(EXIT_FAILURE);
-	}
-	else
-	{
-		ShowStatus("Connect success!\n");
-	}
-
-	if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) )
-		Sql_ShowDebug(sql_handle);
-
-	if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s` (`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100','login server started')", loginlog_db) )
-		Sql_ShowDebug(sql_handle);
-
-	sql_ping_init();
-
-	return 0;
-}
-
-
-//-----------------------------------------------------
-// close DB
-//-----------------------------------------------------
-void mmo_db_close(void)
-{
-	int i, fd;
-
-	//set log.
-	if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100', 'login server shutdown')", loginlog_db) )
-		Sql_ShowDebug(sql_handle);
-
-	for( i = 0; i < MAX_SERVERS; ++i )
-	{
-		fd = server[i].fd;
-		if( session_isValid(fd) )
-		{// Clean only data related to servers we are connected to. [Skotlex]
-			if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index` = '%d'", i) )
-				Sql_ShowDebug(sql_handle);
-			do_close(fd);
-		}
-	}
-	Sql_Free(sql_handle);
-	sql_handle = NULL;
-	ShowStatus("close DB connect....\n");
-	if( login_fd > 0 )
-		do_close(login_fd);
-}
-
-//-----------------------------------------------------
-// periodic ip address synchronization
-//-----------------------------------------------------
-static int sync_ip_addresses(int tid, unsigned int tick, int id, intptr data)
-{
-	uint8 buf[2];
-	ShowInfo("IP Sync in progress...\n");
-	WBUFW(buf,0) = 0x2735;
-	charif_sendallwos(-1, buf, 2);
-	return 0;
-}
-
-//-----------------------------------------------------
-// encrypted/unencrypted password check
-//-----------------------------------------------------
-bool check_encrypted(const char* str1, const char* str2, const char* passwd)
-{
-	char md5str[64], md5bin[32];
-
-	snprintf(md5str, sizeof(md5str), "%s%s", str1, str2);
-	md5str[sizeof(md5str)-1] = '\0';
-	MD5_String2binary(md5str, md5bin);
-
-	return (0==memcmp(passwd, md5bin, 16));
-}
-
-bool check_password(struct login_session_data* ld, int passwdenc, const char* passwd, const char* refpass)
-{	
-	if(passwdenc == 0)
-	{
-		return (0==strcmp(passwd, refpass));
-	}
-	else if (ld)
-	{
-		// password mode set to 1 -> (md5key, refpass) enable with <passwordencrypt></passwordencrypt>
-		// password mode set to 2 -> (refpass, md5key) enable with <passwordencrypt2></passwordencrypt2>
-		
-		return ((passwdenc&0x01) && check_encrypted(ld->md5key, refpass, passwd)) ||
-		       ((passwdenc&0x02) && check_encrypted(refpass, ld->md5key, passwd));
-	}
-	return false;
-}
-
-
-//-----------------------------------------------------
-// Make new account
-//-----------------------------------------------------
-int mmo_auth_new(struct mmo_account* account)
-{
-	static int num_regs = 0; // registration counter
-	unsigned int tick = gettick();
-
-	char md5buf[32+1];
-	time_t expiration_time = 0;
-	SqlStmt* stmt;
-	int result = 0;
-
-	//Account Registration Flood Protection by [Kevin]
-	if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs )
-	{
-		ShowNotice("Account registration denied (registration limit exceeded)\n");
-		return 3;
-	}
-
-	// check if the account doesn't exist already
-	stmt = SqlStmt_Malloc(sql_handle);
-	if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "SELECT `%s` FROM `%s` WHERE `userid` = ?", login_db_userid, login_db)
-	||  SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH))
-	||  SQL_SUCCESS != SqlStmt_Execute(stmt) )
-	{
-		SqlStmt_ShowDebug(stmt);
-		result = 1;// error
-	}
-	else if( SqlStmt_NumRows(stmt) > 0 )
-		result = 1;// username already taken
-	SqlStmt_Free(stmt);
-	if( result )
-		return result;// error or incorrect user
-
-	if( login_config.start_limited_time != -1 )
-		expiration_time = time(NULL) + login_config.start_limited_time;
-
-	// insert new entry into db
-	//TODO: error checking
-	stmt = SqlStmt_Malloc(sql_handle);
-	SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`, `connect_until`) VALUES (?, ?, '%c', 'a@a.com', '%d')", login_db, login_db_userid, login_db_user_pass, account->sex, expiration_time);
-	SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH));
-	if( login_config.use_md5_passwds )
-	{
-		MD5_String(account->pass, md5buf);
-		SqlStmt_BindParam(stmt, 1, SQLDT_STRING, md5buf, 32);
-	}
-	else
-		SqlStmt_BindParam(stmt, 1, SQLDT_STRING, account->pass, strnlen(account->pass, NAME_LENGTH));
-	SqlStmt_Execute(stmt);
-
-	ShowNotice("Account creation (account %s, id: %d, pass: %s, sex: %c)\n", account->userid, (int)SqlStmt_LastInsertId(stmt), account->pass, account->sex);
-	SqlStmt_Free(stmt);
-
-	if( DIFF_TICK(tick, new_reg_tick) > 0 )
-	{// Update the registration check.
-		num_regs = 0;
-		new_reg_tick = tick + time_allowed*1000;
-	}
-	++num_regs;
-
-	return 0;
-}
-
-
-//-----------------------------------------------------
-// Check/authentication of a connection
-//-----------------------------------------------------
-int mmo_auth(struct login_session_data* sd)
-{
-	time_t unban_time;
-	char esc_userid[NAME_LENGTH*2+1];// escaped username
-	char user_password[256], password[256];
-	long expiration_time;
-	int state;
-	size_t len;
-	char* data;
-
-	char ip[16];
-	ip2str(session[sd->fd]->client_addr, ip);
-
-	// DNS Blacklist check
-	if( login_config.use_dnsbl )
-	{
-		char r_ip[16];
-		char ip_dnsbl[256];
-		char* dnsbl_serv;
-		bool matched = false;
-		uint8* sin_addr = (uint8*)&session[sd->fd]->client_addr;
-
-		sprintf(r_ip, "%u.%u.%u.%u", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]);
-
-		for( dnsbl_serv = strtok(login_config.dnsbl_servs,","); !matched && dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",") )
-		{
-			sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv);
-			if( host2ip(ip_dnsbl) )
-				matched = true;
-		}
-
-		if( matched )
-		{
-			ShowInfo("DNSBL: (%s) Blacklisted. User Kicked.\n", r_ip);
-			return 3;
-		}
-	}
-
-	//Client Version check
-	if( login_config.check_client_version && sd->version != login_config.client_version_to_connect )
-		return 5;
-
-	len = strnlen(sd->userid, NAME_LENGTH);
-
-	// Account creation with _M/_F
-	if( login_config.new_account_flag )
-	{
-		if( len > 2 && strnlen(sd->passwd, NAME_LENGTH) > 0 && // valid user and password lengths
-			sd->passwdenc == 0 && // unencoded password
-			sd->userid[len-2] == '_' && memchr("FfMm", sd->userid[len-1], 4) ) // _M/_F suffix
-		{
-			struct mmo_account acc;
-			int result;
-
-			len -= 2;
-			sd->userid[len] = '\0';
-
-			memset(&acc, '\0', sizeof(acc));
-			safestrncpy(acc.userid, sd->userid, NAME_LENGTH);
-			safestrncpy(acc.pass, sd->passwd, NAME_LENGTH);
-			safestrncpy(acc.email, "a@a.com", sizeof(acc.email));
-			acc.sex = TOUPPER(sd->userid[len+1]);
-
-			result = mmo_auth_new(&acc);
-			if( result )
-				return result;// Failed to make account. [Skotlex].
-		}
-	}
-
-	// escape username
-	Sql_EscapeStringLen(sql_handle, esc_userid, sd->userid, len);
-
-	// retrieve login entry for the specified username
-	if( SQL_ERROR == Sql_Query(sql_handle,
-		"SELECT `%s`,`%s`,`lastlogin`,`sex`,`connect_until`,`ban_until`,`state`,`%s` FROM `%s` WHERE `%s`= %s '%s'",
-		login_db_account_id, login_db_user_pass, login_db_level,
-		login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) )
-		Sql_ShowDebug(sql_handle);
-
-	if( Sql_NumRows(sql_handle) == 0 ) // no such entry
-	{
-		ShowNotice("auth failed: no such account '%s'\n", esc_userid);
-		Sql_FreeResult(sql_handle);
-		return 0;
-	}
-
-	Sql_NextRow(sql_handle); //TODO: error checking?
-
-	Sql_GetData(sql_handle, 0, &data, NULL); sd->account_id = atoi(data);
-	Sql_GetData(sql_handle, 1, &data, &len); safestrncpy(password, data, sizeof(password));
-	Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(sd->lastlogin, data, sizeof(sd->lastlogin));
-	Sql_GetData(sql_handle, 3, &data, NULL); sd->sex = *data;
-	Sql_GetData(sql_handle, 4, &data, NULL); expiration_time = atol(data);
-	Sql_GetData(sql_handle, 5, &data, NULL); unban_time = atol(data);
-	Sql_GetData(sql_handle, 6, &data, NULL); state = atoi(data);
-	Sql_GetData(sql_handle, 7, &data, NULL); sd->level = atoi(data);
-	if( len > sizeof(password) - 1 )
-		ShowDebug("mmo_auth: password buffer is too small (len=%u,buflen=%u)\n", len, sizeof(password));
-	if( sd->level > 99 )
-		sd->level = 99;
-
-	Sql_FreeResult(sql_handle);
-
-	if( login_config.use_md5_passwds )
-		MD5_String(sd->passwd, user_password);
-	else
-		safestrncpy(user_password, sd->passwd, NAME_LENGTH);
-
-	if( !check_password(sd, sd->passwdenc, user_password, password) )
-	{
-		ShowInfo("Invalid password (account: '%s', pass: '%s', received pass: '%s', ip: %s)\n",
-			esc_userid, password, (sd->passwdenc) ? "[MD5]" : user_password, ip);
-		return 1; // 1 = Incorrect Password
-	}
-
-	if( expiration_time != 0 && expiration_time < time(NULL) )
-		return 2; // 2 = This ID is expired
-
-	if( unban_time != 0 && unban_time > time(NULL) )
-		return 6; // 6 = Your are Prohibited to log in until %s
-
-	if( state )
-	{
-		ShowInfo("Connection refused (account: %s, pass: %s, state: %d, ip: %s)\n", sd->userid, sd->passwd, state, ip);
-		return state - 1;
-	}
-
-	sd->login_id1 = rand();
-	sd->login_id2 = rand();
-
-	if( sd->sex != 'S' && sd->account_id < START_ACCOUNT_NUM )
-		ShowWarning("Account %s has account id %d! Account IDs must be over %d to work properly!\n", sd->userid, sd->account_id, START_ACCOUNT_NUM);
-
-	if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount`+1, `last_ip`='%s', `ban_until`='0', `state`='0' WHERE `%s` = '%d'",
-		login_db, ip, login_db_account_id, sd->account_id) )
-		Sql_ShowDebug(sql_handle);
-
-	return -1; // account OK
-}
-
-static int online_db_setoffline(DBKey key, void* data, va_list ap)
-{
-	struct online_login_data* p = (struct online_login_data*)data;
-	int server = va_arg(ap, int);
-	if( server == -1 )
-	{
-		p->char_server = -1;
-		if( p->waiting_disconnect != -1 )
-		{
-			delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-			p->waiting_disconnect = -1;
-		}
-	}
-	else if( p->char_server == server )
-		p->char_server = -2; //Char server disconnected.
-	return 0;
-}
-
-//--------------------------------
-// Packet parsing for char-servers
-//--------------------------------
-int parse_fromchar(int fd)
-{
-	unsigned int i;
-	int id;
-	uint32 ipl;
-	char ip[16];
-
-	ARR_FIND( 0, MAX_SERVERS, id, server[id].fd == fd );
-	if( id == MAX_SERVERS )
-	{// not a char server
-		set_eof(fd);
-		do_close(fd);
-		return 0;
-	}
-
-	if( session[fd]->flag.eof )
-	{
-		ShowStatus("Char-server '%s' has disconnected.\n", server[id].name);
-		online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char server to offline.
-		if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `sstatus` WHERE `index`='%d'", id) )
-			Sql_ShowDebug(sql_handle);
-		memset(&server[id], 0, sizeof(struct mmo_char_server));
-		server[id].fd = -1;
-		do_close(fd);
-		return 0;
-	}
-
-	ipl = server[id].ip;
-	ip2str(ipl, ip);
-
-	while( RFIFOREST(fd) >= 2 )
-	{
-		uint16 command = RFIFOW(fd,0);
-
-		switch( command )
-		{
-
-		case 0x2709: // request from map-server via char-server to reload GM accounts
-			RFIFOSKIP(fd,2);
-			ShowStatus("Char-server '%s': Request to re-load GM configuration file (ip: %s).\n", server[id].name, ip);
-			if( login_config.log_login )
-			{
-				if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name) )
-					Sql_ShowDebug(sql_handle);
-			}
-			read_gm_account();
-			// send GM accounts to all char-servers
-			send_GM_accounts(-1);
-		break;
-
-		case 0x2712: // request from char-server to authenticate an account
-			if( RFIFOREST(fd) < 19 )
-				return 0;
-		{
-			struct auth_node* node;
-
-			int account_id = RFIFOL(fd,2);
-			uint32 login_id1 = RFIFOL(fd,6);
-			uint32 login_id2 = RFIFOL(fd,10);
-			char sex = sex_num2str(RFIFOB(fd,14));
-			uint32 ip_ = ntohl(RFIFOL(fd,15));
-			RFIFOSKIP(fd,19);
-
-			node = (struct auth_node*)idb_get(auth_db, account_id);
-			if( node != NULL &&
-			    node->account_id == account_id &&
-				node->login_id1  == login_id1 &&
-				node->login_id2  == login_id2 &&
-				node->sex        == sex &&
-				node->ip         == ip_ )
-			{// found
-				uint32 expiration_time;
-				char email[40];
-
-				// each auth entry can only be used once
-				idb_remove(auth_db, account_id);
-
-				// retrieve email and account expiration time
-				if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) )
-					Sql_ShowDebug(sql_handle);
-				if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-				{
-					char* data = NULL;
-					size_t len = 0;
-
-					Sql_GetData(sql_handle, 0, &data, &len); safestrncpy(email, data, sizeof(email));
-					Sql_GetData(sql_handle, 1, &data, NULL); expiration_time = (uint32)strtoul(data, NULL, 10);
-					if( len > sizeof(email) )
-						ShowDebug("parse_fromchar:0x2712: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email));
-
-					Sql_FreeResult(sql_handle);
-				}
-				else
-				{
-					memset(email, 0, sizeof(email));
-					expiration_time = 0;
-				}
-
-				// send ack
-				WFIFOHEAD(fd,59);
-				WFIFOW(fd,0) = 0x2713;
-				WFIFOL(fd,2) = account_id;
-				WFIFOL(fd,6) = login_id1;
-				WFIFOL(fd,10) = login_id2;
-				WFIFOB(fd,14) = 0;
-				memcpy(WFIFOP(fd,15), email, 40);
-				WFIFOL(fd,55) = expiration_time;
-				WFIFOSET(fd,59);
-			}
-			else
-			{// authentication not found
-				ShowStatus("Char-server '%s': authentication of the account %d REFUSED (ip: %s).\n", server[id].name, account_id, ip);
-				WFIFOHEAD(fd,59);
-				WFIFOW(fd,0) = 0x2713;
-				WFIFOL(fd,2) = account_id;
-				WFIFOL(fd,6) = login_id1;
-				WFIFOL(fd,10) = login_id2;
-				WFIFOB(fd,14) = 1;
-				// It is unnecessary to send email
-				// It is unnecessary to send validity date of the account
-				WFIFOSET(fd,59);
-			}
-		}
-		break;
-
-		case 0x2714:
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-		{
-			int users = RFIFOL(fd,2);
-			RFIFOSKIP(fd,6);
-
-			// how many users on world? (update)
-			if( server[id].users != users )
-			{
-				ShowStatus("set users %s : %d\n", server[id].name, users);
-
-				server[id].users = users;
-				if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id) )
-					Sql_ShowDebug(sql_handle);
-			}
-		}
-		break;
-
-		case 0x2716: // received an e-mail/limited time request, because a player comes back from a map-server to the char-server
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-		{
-			uint32 expiration_time = 0;
-			char email[40] = "";
-
-			int account_id = RFIFOL(fd,2);
-			RFIFOSKIP(fd,6);
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-			{
-				char* data;
-				size_t len;
-
-				Sql_GetData(sql_handle, 0, &data, &len);
-				safestrncpy(email, data, sizeof(email));
-
-				Sql_GetData(sql_handle, 1, &data, NULL);
-				expiration_time = (uint32)strtoul(data, NULL, 10);
-
-				Sql_FreeResult(sql_handle);
-			}
-
-			WFIFOHEAD(fd,50);
-			WFIFOW(fd,0) = 0x2717;
-			WFIFOL(fd,2) = account_id;
-			safestrncpy((char*)WFIFOP(fd,6), email, 40);
-			WFIFOL(fd,46) = expiration_time;
-			WFIFOSET(fd,50);
-		}
-		break;
-
-		case 0x2719: // ping request from charserver
-			if( RFIFOREST(fd) < 2 )
-				return 0;
-			RFIFOSKIP(fd,2);
-
-			WFIFOHEAD(fd,2);
-			WFIFOW(fd,0) = 0x2718;
-			WFIFOSET(fd,2);
-		break;
-
-		// Map server send information to change an email of an account via char-server
-		case 0x2722:	// 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B
-			if (RFIFOREST(fd) < 86)
-				return 0;
-		{
-			char actual_email[40];
-			char new_email[40];
-			int account_id = RFIFOL(fd,2);
-			safestrncpy(actual_email, (char*)RFIFOP(fd,6), 40);
-			safestrncpy(new_email, (char*)RFIFOP(fd,46), 40);
-			RFIFOSKIP(fd, 86);
-
-			if( e_mail_check(actual_email) == 0 )
-				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command), but actual email is invalid (account: %d, ip: %s)\n", server[id].name, account_id, ip);
-			else if( e_mail_check(new_email) == 0 )
-				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a invalid new e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
-			else if( strcmpi(new_email, "a@a.com") == 0 )
-				ShowNotice("Char-server '%s': Attempt to modify an e-mail on an account (@email GM command) with a default e-mail (account: %d, ip: %s)\n", server[id].name, account_id, ip);
-			else if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-			{
-				char* data;
-				size_t len;
-
-				Sql_GetData(sql_handle, 1, &data, &len);
-				if( strncasecmp(data, actual_email, sizeof(actual_email)) == 0 )
-				{
-					char esc_user_id[NAME_LENGTH*2+1];
-					char esc_new_email[sizeof(new_email)*2+1];
-
-					Sql_GetData(sql_handle, 0, &data, &len);
-					Sql_EscapeStringLen(sql_handle, esc_user_id, data, len);
-					Sql_EscapeStringLen(sql_handle, esc_new_email, new_email, strnlen(new_email, sizeof(new_email)));
-
-					if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, esc_new_email, login_db_account_id, account_id) )
-						Sql_ShowDebug(sql_handle);
-					ShowInfo("Char-server '%s': Modify an e-mail on an account (@email GM command) (account: %d ('%s'), new e-mail: '%s', ip: %s).\n", server[id].name, account_id, esc_user_id, esc_new_email, ip);
-				}
-				Sql_FreeResult(sql_handle);
-			}
-		}
-		break;
-
-		case 0x2724: // Receiving an account state update request from a map-server (relayed via char-server)
-			if (RFIFOREST(fd) < 10)
-				return 0;
-		{
-			int account_id = RFIFOL(fd,2);
-			int state = RFIFOL(fd,6);
-			RFIFOSKIP(fd,10);
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-			{
-				char* data;
-
-				Sql_GetData(sql_handle, 0, &data, NULL);
-				if( atoi(data) != state && state != 0 )
-				{
-					uint8 buf[11];
-					WBUFW(buf,0) = 0x2731;
-					WBUFL(buf,2) = account_id;
-					WBUFB(buf,6) = 0; // 0: change of state, 1: ban
-					WBUFL(buf,7) = state; // status or final date of a banishment
-					charif_sendallwos(-1, buf, 11);
-				}
-				Sql_FreeResult(sql_handle);
-			}
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, state, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-		}
-		break;
-
-		case 0x2725: // Receiving of map-server via char-server a ban request
-			if (RFIFOREST(fd) < 18)
-				return 0;
-		{
-			struct tm *tmtime;
-			time_t tmptime = 0;
-			time_t timestamp = time(NULL);
-
-			int account_id = RFIFOL(fd,2);
-			int year = (short)RFIFOW(fd,6);
-			int month = (short)RFIFOW(fd,8);
-			int mday = (short)RFIFOW(fd,10);
-			int hour = (short)RFIFOW(fd,12);
-			int min = (short)RFIFOW(fd,14);
-			int sec = (short)RFIFOW(fd,16);
-			RFIFOSKIP(fd,18);
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-			{
-				char* data;
-
-				Sql_GetData(sql_handle, 0, &data, NULL);
-				tmptime = (time_t)strtoul(data, NULL, 10);
-				if( tmptime > time(NULL) )
-					timestamp = tmptime;
-			}
-			tmtime = localtime(&timestamp);
-			tmtime->tm_year = tmtime->tm_year + year;
-			tmtime->tm_mon  = tmtime->tm_mon  + month;
-			tmtime->tm_mday = tmtime->tm_mday + mday;
-			tmtime->tm_hour = tmtime->tm_hour + hour;
-			tmtime->tm_min  = tmtime->tm_min  + min;
-			tmtime->tm_sec  = tmtime->tm_sec  + sec;
-			timestamp = mktime(tmtime);
-			if( timestamp != (time_t)-1 )
-			{
-				if( timestamp <= time(NULL) )
-					timestamp = 0;
-				if( tmptime != timestamp )
-				{
-					if( timestamp != 0 )
-					{
-						uint8 buf[11];
-						WBUFW(buf,0) = 0x2731;
-						WBUFL(buf,2) = account_id;
-						WBUFB(buf,6) = 1; // 0: change of statut, 1: ban
-						WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment
-						charif_sendallwos(-1, buf, 11);
-					}
-					ShowNotice("Account: %d Banned until: %lu\n", account_id, (unsigned long)timestamp);
-					if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until` = '%lu' WHERE `%s` = '%d'", login_db, (unsigned long)timestamp, login_db_account_id, account_id) )
-						Sql_ShowDebug(sql_handle);
-				}
-			}
-		}
-		break;
-
-		case 0x2727: // Change of sex (sex is reversed)
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-		{
-			int account_id = RFIFOL(fd,2);
-			RFIFOSKIP(fd,6);
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `sex` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-			{
-				unsigned char buf[7];
-				int sex;
-				char* data;
-
-				Sql_GetData(sql_handle, 0, &data, NULL);
-				sex = ( *data == 'M' ) ? 'F' : 'M'; //Change gender
-
-				if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, sex, login_db_account_id, account_id) )
-					Sql_ShowDebug(sql_handle);
-
-				WBUFW(buf,0) = 0x2723;
-				WBUFL(buf,2) = account_id;
-				WBUFB(buf,6) = sex_str2num(sex);
-				charif_sendallwos(-1, buf, 7);
-			}
-		}
-		break;
-
-		case 0x2728:	// save account_reg2
-			if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) )
-				return 0;
-			if( RFIFOL(fd,4) > 0 )
-			{
-				SqlStmt* stmt;
-				int account_id;
-				size_t off;
-
-				account_id = RFIFOL(fd,4);
-
-				//Delete all global account variables....
-				if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d';", reg_db, account_id) )
-					Sql_ShowDebug(sql_handle);
-
-				//Proceed to insert them....
-				stmt = SqlStmt_Malloc(sql_handle);
-				if( SQL_ERROR == SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , ? , ?);",  reg_db, account_id) )
-					SqlStmt_ShowDebug(stmt);
-				for( i = 0, off = 13; i < ACCOUNT_REG2_NUM && off < RFIFOW(fd,2); ++i )
-				{
-					char* p;
-					size_t len;
-
-					// str
-					p = (char*)RFIFOP(fd,off);
-					len = strlen(p);
-					SqlStmt_BindParam(stmt, 0, SQLDT_STRING, p, len);
-					off += len + 1;
-
-					// value
-					p = (char*)RFIFOP(fd,off);
-					len = strlen(p);
-					SqlStmt_BindParam(stmt, 1, SQLDT_STRING, p, len);
-					off += len + 1;
-
-					if( SQL_ERROR == SqlStmt_Execute(stmt) )
-						SqlStmt_ShowDebug(stmt);
-				}
-				SqlStmt_Free(stmt);
-
-				// Sending information towards the other char-servers.
-				RFIFOW(fd,0) = 0x2729;// reusing read buffer
-				charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2));
-				RFIFOSKIP(fd,RFIFOW(fd,2));
-			}
-		break;
-
-		case 0x272a:	// Receiving of map-server via char-server an unban request
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-		{
-			int account_id = RFIFOL(fd,2);
-			RFIFOSKIP(fd,6);
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
-				Sql_ShowDebug(sql_handle);
-			else if( Sql_NumRows(sql_handle) > 0 )
-			{// Found a match
-				if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until` = '0' WHERE `%s` = '%d'", login_db, login_db_account_id, account_id) )
-					Sql_ShowDebug(sql_handle);
-			}
-		}
-		break;
-
-		case 0x272b:    // Set account_id to online [Wizputer]
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-			add_online_user(id, RFIFOL(fd,2));
-			RFIFOSKIP(fd,6);
-		break;
-
-		case 0x272c:   // Set account_id to offline [Wizputer]
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-			remove_online_user(RFIFOL(fd,2));
-			RFIFOSKIP(fd,6);
-		break;
-
-		case 0x272d:	// Receive list of all online accounts. [Skotlex]
-			if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2))
-				return 0;
-			if( login_config.online_check )
-			{
-				struct online_login_data *p;
-				int aid;
-				uint32 i, users;
-				online_db->foreach(online_db, online_db_setoffline, id); //Set all chars from this char-server offline first
-				users = RFIFOW(fd,4);
-				for (i = 0; i < users; i++) {
-					aid = RFIFOL(fd,6+i*4);
-					p = (struct online_login_data*)idb_ensure(online_db, aid, create_online_user);
-					p->char_server = id;
-					if (p->waiting_disconnect != -1)
-					{
-						delete_timer(p->waiting_disconnect, waiting_disconnect_timer);
-						p->waiting_disconnect = -1;
-					}
-				}
-			}
-			RFIFOSKIP(fd,RFIFOW(fd,2));
-		break;
-
-		case 0x272e: //Request account_reg2 for a character.
-			if (RFIFOREST(fd) < 10)
-				return 0;
-		{
-			size_t off;
-
-			int account_id = RFIFOL(fd,2);
-			int char_id = RFIFOL(fd,6);
-			RFIFOSKIP(fd,10);
-
-			WFIFOHEAD(fd,10000);
-			WFIFOW(fd,0) = 0x2729;
-			WFIFOL(fd,4) = account_id;
-			WFIFOL(fd,8) = char_id;
-			WFIFOB(fd,12) = 1; //Type 1 for Account2 registry
-
-			if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", reg_db, account_id) )
-				Sql_ShowDebug(sql_handle);
-
-			off = 13;
-			while( SQL_SUCCESS == Sql_NextRow(sql_handle) && off < 9000 )
-			{
-				char* data;
-				
-				// str
-				Sql_GetData(sql_handle, 0, &data, NULL);
-				if( *data != '\0' )
-				{
-					off += sprintf((char*)WFIFOP(fd,off), "%s", data)+1; //We add 1 to consider the '\0' in place.
-					
-					// value
-					Sql_GetData(sql_handle, 1, &data, NULL);
-					off += sprintf((char*)WFIFOP(fd,off), "%s", data)+1;
-				}
-			}
-			Sql_FreeResult(sql_handle);
-
-			if( off >= 9000 )
-				ShowWarning("Too many account2 registries for AID %d. Some registries were not sent.\n", account_id);
-
-			WFIFOW(fd,2) = (uint16)off;
-			WFIFOSET(fd,WFIFOW(fd,2));
-		}
-		break;
-
-		case 0x2736: // WAN IP update from char-server
-			if( RFIFOREST(fd) < 6 )
-				return 0;
-			server[id].ip = ntohl(RFIFOL(fd,2));
-			ShowInfo("Updated IP of Server #%d to %d.%d.%d.%d.\n",id, CONVIP(server[id].ip));
-			RFIFOSKIP(fd,6);
-		break;
-
-		case 0x2737: //Request to set all offline.
-			ShowInfo("Setting accounts from char-server %d offline.\n", id);
-			online_db->foreach(online_db, online_db_setoffline, id);
-			RFIFOSKIP(fd,2);
-		break;
-
-		default:
-			ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command);
-			set_eof(fd);
-			return 0;
-		} // switch
-	} // while
-
-	RFIFOSKIP(fd,RFIFOREST(fd));
-	return 0;
-}
-
-//--------------------------------------------
-// Test to know if an IP come from LAN or WAN.
-//--------------------------------------------
-int lan_subnetcheck(uint32 ip)
-{
-	int i;
-	ARR_FIND( 0, subnet_count, i, (subnet[i].char_ip & subnet[i].mask) == (ip & subnet[i].mask) );
-	return ( i < subnet_count ) ? subnet[i].char_ip : 0;
-}
-
-int login_ip_ban_check(uint32 ip)
-{
-	uint8* p = (uint8*)&ip;
-	char* data = NULL;
-	int matches;
-
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u'",
-		p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) )
-	{
-		Sql_ShowDebug(sql_handle);
-		// close connection because we can't verify their connectivity.
-		return 1;
-	}
-
-	if( SQL_ERROR == Sql_NextRow(sql_handle) )
-		return 1;// Shouldn't happen, but just in case...
-
-	Sql_GetData(sql_handle, 0, &data, NULL);
-	matches = atoi(data);
-	Sql_FreeResult(sql_handle);
-
-	if( matches == 0 )
-		return 0;// No ban
-
-	// ip ban ok.
-	ShowInfo("Packet from banned ip : %u.%u.%u.%u\n", CONVIP(ip));
-
-	if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip) )
-		Sql_ShowDebug(sql_handle);
-	return 1;
-}
-
-void login_auth_ok(struct login_session_data* sd)
-{
-	int fd = sd->fd;
-	uint32 ip = session[fd]->client_addr;
-
-	char esc_userid[NAME_LENGTH*2+1];
-	uint8 server_num, n;
-	uint32 subnet_char_ip;
-	struct auth_node* node;
-	int i;
-
-	Sql_EscapeStringLen(sql_handle, esc_userid, sd->userid, strlen(sd->userid));
-
-	if( sd->level < login_config.min_level_to_connect )
-	{
-		ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d).\n", login_config.min_level_to_connect, sd->userid, sd->level);
-		WFIFOHEAD(fd,3);
-		WFIFOW(fd,0) = 0x81;
-		WFIFOB(fd,2) = 1; // 01 = Server closed
-		WFIFOSET(fd,3);
-		return;
-	}
-
-	server_num = 0;
-	for( i = 0; i < MAX_SERVERS; ++i )
-		if( session_isValid(server[i].fd) )
-			server_num++;
-
-	if( server_num == 0 )
-	{// if no char-server, don't send void list of servers, just disconnect the player with proper message
-		ShowStatus("Connection refused: there is no char-server online (account: %s).\n", sd->userid);
-		WFIFOHEAD(fd,3);
-		WFIFOW(fd,0) = 0x81;
-		WFIFOB(fd,2) = 1; // 01 = Server closed
-		WFIFOSET(fd,3);
-		return;
-	}
-
-	if( login_config.online_check )
-	{
-		struct online_login_data* data = (struct online_login_data*)idb_get(online_db, sd->account_id);
-		if( data )
-		{// account is already marked as online!
-			if( data->char_server > -1 )
-			{// Request char servers to kick this account out. [Skotlex]
-				uint8 buf[6];
-				ShowNotice("User '%s' is already online - Rejected.\n", sd->userid);
-				WBUFW(buf,0) = 0x2734;
-				WBUFL(buf,2) = sd->account_id;
-				charif_sendallwos(-1, buf, 6);
-				if( data->waiting_disconnect == -1 )
-					data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
-
-				WFIFOHEAD(fd,3);
-				WFIFOW(fd,0) = 0x81;
-				WFIFOB(fd,2) = 8; // 08 = Server still recognizes your last login
-				WFIFOSET(fd,3);
-				return;
-			}
-			else
-			if( data->char_server == -1 )
-			{// client has authed but did not access char-server yet
-				// wipe previous session
-				idb_remove(auth_db, sd->account_id);
-				remove_online_user(sd->account_id);
-				data = NULL;
-			}
-		}
-	}
-
-	if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ip, esc_userid) )
-		Sql_ShowDebug(sql_handle);
-
-	if( sd->level > 0 )
-		ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", sd->level, sd->userid);
-	else
-		ShowStatus("Connection of the account '%s' accepted.\n", sd->userid);
-
-	WFIFOHEAD(fd,47+32*server_num);
-	WFIFOW(fd,0) = 0x69;
-	WFIFOW(fd,2) = 47+32*server_num;
-	WFIFOL(fd,4) = sd->login_id1;
-	WFIFOL(fd,8) = sd->account_id;
-	WFIFOL(fd,12) = sd->login_id2;
-	WFIFOL(fd,16) = 0; // in old version, that was for ip (not more used)
-	//memcpy(WFIFOP(fd,20), sd->lastlogin, 24); // in old version, that was for name (not more used)
-	WFIFOW(fd,44) = 0; // unknown
-	WFIFOB(fd,46) = sex_str2num(sd->sex);
-	for( i = 0, n = 0; i < MAX_SERVERS; ++i )
-	{
-		if( !session_isValid(server[i].fd) )
-			continue;
-
-		subnet_char_ip = lan_subnetcheck(ip); // Advanced subnet check [LuzZza]
-		WFIFOL(fd,47+n*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip);
-		WFIFOW(fd,47+n*32+4) = ntows(htons(server[i].port)); // [!] LE byte order here [!]
-		memcpy(WFIFOP(fd,47+n*32+6), server[i].name, 20);
-		WFIFOW(fd,47+n*32+26) = server[i].users;
-		WFIFOW(fd,47+n*32+28) = server[i].maintenance;
-		WFIFOW(fd,47+n*32+30) = server[i].new_;
-		n++;
-	}
-	WFIFOSET(fd,47+32*server_num);
-
-	// create temporary auth entry
-	CREATE(node, struct auth_node, 1);
-	node->account_id = sd->account_id;
-	node->login_id1 = sd->login_id1;
-	node->login_id2 = sd->login_id2;
-	node->sex = sd->sex;
-	node->ip = ip;
-	idb_put(auth_db, sd->account_id, node);
-
-	if( login_config.online_check )
-	{
-		struct online_login_data* data;
-
-		// mark client as 'online'
-		data = add_online_user(-1, sd->account_id);
-
-		// schedule deletion of this node
-		data->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, waiting_disconnect_timer, sd->account_id, 0);
-	}
-}
-
-void login_auth_failed(struct login_session_data* sd, int result)
-{
-	int fd = sd->fd;
-	uint32 ip = session[fd]->client_addr;
-	char esc_userid[NAME_LENGTH*2+1];
-
-	Sql_EscapeStringLen(sql_handle, esc_userid, sd->userid, strlen(sd->userid));
-
-	if (login_config.log_login)
-	{
-		const char* error;
-		switch( result ) {
-		case   0: error = "Unregistered ID."; break; // 0 = Unregistered ID
-		case   1: error = "Incorrect Password."; break; // 1 = Incorrect Password
-		case   2: error = "Account Expired."; break; // 2 = This ID is expired
-		case   3: error = "Rejected from server."; break; // 3 = Rejected from Server
-		case   4: error = "Blocked by GM."; break; // 4 = You have been blocked by the GM Team
-		case   5: error = "Not latest game EXE."; break; // 5 = Your Game's EXE file is not the latest version
-		case   6: error = "Banned."; break; // 6 = Your are Prohibited to log in until %s
-		case   7: error = "Server Over-population."; break; // 7 = Server is jammed due to over populated
-		case   8: error = "Account limit from company"; break; // 8 = No more accounts may be connected from this company
-		case   9: error = "Ban by DBA"; break; // 9 = MSI_REFUSE_BAN_BY_DBA
-		case  10: error = "Email not confirmed"; break; // 10 = MSI_REFUSE_EMAIL_NOT_CONFIRMED
-		case  11: error = "Ban by GM"; break; // 11 = MSI_REFUSE_BAN_BY_GM
-		case  12: error = "Working in DB"; break; // 12 = MSI_REFUSE_TEMP_BAN_FOR_DBWORK
-		case  13: error = "Self Lock"; break; // 13 = MSI_REFUSE_SELF_LOCK
-		case  14: error = "Not Permitted Group"; break; // 14 = MSI_REFUSE_NOT_PERMITTED_GROUP
-		case  15: error = "Not Permitted Group"; break; // 15 = MSI_REFUSE_NOT_PERMITTED_GROUP
-		case  99: error = "Account gone."; break; // 99 = This ID has been totally erased
-		case 100: error = "Login info remains."; break; // 100 = Login information remains at %s
-		case 101: error = "Hacking investigation."; break; // 101 = Account has been locked for a hacking investigation. Please contact the GM Team for more information
-		case 102: error = "Bug investigation."; break; // 102 = This account has been temporarily prohibited from login due to a bug-related investigation
-		case 103: error = "Deleting char."; break; // 103 = This character is being deleted. Login is temporarily unavailable for the time being
-		case 104: error = "Deleting spouse char."; break; // 104 = This character is being deleted. Login is temporarily unavailable for the time being
-		default : error = "Unknown Error."; break;
-		}
-
-		if( SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ip, esc_userid, result, error) )
-			Sql_ShowDebug(sql_handle);
-	}
-
-	if( result == 1 && login_config.dynamic_pass_failure_ban && login_config.log_login ) // failed password
-	{
-		unsigned long failures = 0;
-		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE",
-			loginlog_db, ip, login_config.dynamic_pass_failure_ban_interval) )// how many times failed account? in one ip.
-			Sql_ShowDebug(sql_handle);
-
-		//check query result
-		if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-		{
-			char* data;
-			Sql_GetData(sql_handle, 0, &data, NULL);
-			failures = strtoul(data, NULL, 10);
-			Sql_FreeResult(sql_handle);
-		}
-		if( failures >= login_config.dynamic_pass_failure_ban_limit )
-		{
-			uint8* p = (uint8*)&ip;
-			if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() +  INTERVAL %d MINUTE ,'Password error ban: %s')", p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration, esc_userid) )
-				Sql_ShowDebug(sql_handle);
-		}
-	}
-
-	WFIFOHEAD(fd,23);
-	WFIFOW(fd,0) = 0x6a;
-	WFIFOB(fd,2) = (uint8)result;
-	if( result != 6 )
-		memset(WFIFOP(fd,3), '\0', 20);
-	else
-	{// 6 = Your are Prohibited to log in until %s
-		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'", login_db, login_db_userid, (login_config.case_sensitive ? "BINARY" : ""), esc_userid) )
-			Sql_ShowDebug(sql_handle);
-		else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
-		{
-			char* data;
-			time_t unban_time;
-
-			Sql_GetData(sql_handle, 0, &data, NULL);
-			unban_time = (time_t)strtoul(data, NULL, 10);
-			Sql_FreeResult(sql_handle);
-
-			strftime((char*)WFIFOP(fd,3), 20, login_config.date_format, localtime(&unban_time));
-		}
-	}
-	WFIFOSET(fd,23);
-}
-
-//----------------------------------------------------------------------------------------
-// Default packet parsing (normal players or administation/char-server connection requests)
-//----------------------------------------------------------------------------------------
-int parse_login(int fd)
-{
-	struct login_session_data* sd = session[fd]->session_data;
-	int result;
-	uint32 ipl;
-	char ip[16];
-
-	if( session[fd]->flag.eof )
-	{
-		do_close(fd);
-		return 0;
-	}
-
-	if( sd == NULL ) {
-		sd = CREATE(session[fd]->session_data, struct login_session_data, 1);
-		sd->fd = fd;
-	}		
-
-	ipl = session[fd]->client_addr;
-	ip2str(ipl, ip);
-
-	while( RFIFOREST(fd) >= 2 )
-	{
-		uint16 command = RFIFOW(fd,0);
-
-		switch( command )
-		{
-
-		case 0x0200:		// New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive.
-			if (RFIFOREST(fd) < 26)
-				return 0;
-			RFIFOSKIP(fd,26);
-		break;
-
-		case 0x0204:		// New alive packet: structure: 0x204 <encrypted.account.userid>.16B. (new ragexe from 22 june 2004)
-			if (RFIFOREST(fd) < 18)
-				return 0;
-			RFIFOSKIP(fd,18);
-		break;
-
-		case 0x0064:		// request client login
-		case 0x01dd:		// request client login (encryption mode)
-		case 0x0277:		// New login packet (kRO 2006-04-24aSakexe langtype 0)
-		case 0x02b0:		// New login packet (kRO 2007-05-14aSakexe langtype 0)
-		{
-			size_t packet_len = RFIFOREST(fd); // assume no other packet was sent
-
-			// Perform ip-ban check
-			if( login_config.ipban && login_ip_ban_check(ipl) )
-			{
-				ShowStatus("Connection refused: IP isn't authorised (deny/allow, ip: %s).\n", ip);
-				WFIFOHEAD(fd,23);
-				WFIFOW(fd,0) = 0x6a;
-				WFIFOB(fd,2) = 3; // 3 = Rejected from Server
-				WFIFOSET(fd,23);
-				RFIFOSKIP(fd,packet_len);
-				set_eof(fd);
-				break;
-			}
-
-			if( (command == 0x0064 && packet_len < 55)
-			||  (command == 0x01dd && packet_len < 47)
-			||  (command == 0x0277 && packet_len < 84)
-			||  (command == 0x02b0 && packet_len < 85) )
-				return 0;
-
-			// S 0064 <version>.l <account name>.24B <password>.24B <version2>.B
-			// S 01dd <version>.l <account name>.24B <md5 binary>.16B <version2>.B
-			// S 0277 <version>.l <account name>.24B <password>.24B <junk?>.29B <version2>.B
-			// S 02b0 <version>.l <account name>.24B <password>.24B <junk?>.30B <version2>.B
-
-			sd->version = RFIFOL(fd,2);
-			safestrncpy(sd->userid, (char*)RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated?
-			if (command != 0x01dd) {
-				ShowStatus("Request for connection of %s (ip: %s).\n", sd->userid, ip);
-				safestrncpy(sd->passwd, (char*)RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated?
-				sd->passwdenc = 0;
-			} else {
-				ShowStatus("Request for connection (encryption mode) of %s (ip: %s).\n", sd->userid, ip);
-				memcpy(sd->passwd, RFIFOP(fd,30), 16); sd->passwd[16] = '\0'; // raw binary data here!
-				sd->passwdenc = PASSWORDENC;
-			}
-			RFIFOSKIP(fd,packet_len);
-
-			result = mmo_auth(sd);
-
-			if( result == -1 )
-				login_auth_ok(sd);
-			else
-				login_auth_failed(sd, result);
-		}
-		break;
-
-		case 0x01db:	// Sending request of the coding key
-			RFIFOSKIP(fd,2);
-		{
-			unsigned int i;
-
-			memset(sd->md5key, '\0', sizeof(sd->md5key));
-			sd->md5keylen = (uint16)(12 + rand() % 4);
-			for( i = 0; i < sd->md5keylen; ++i )
-				sd->md5key[i] = (char)(1 + rand() % 255);
-
-			WFIFOHEAD(fd,4 + sd->md5keylen);
-			WFIFOW(fd,0) = 0x01dc;
-			WFIFOW(fd,2) = 4 + sd->md5keylen;
-			memcpy(WFIFOP(fd,4), sd->md5key, sd->md5keylen);
-			WFIFOSET(fd,WFIFOW(fd,2));
-		}
-		break;
-
-		case 0x2710:	// Connection request of a char-server
-			if (RFIFOREST(fd) < 86)
-				return 0;
-		{
-			char esc_userid[NAME_LENGTH*2+1];
-			char server_name[20];
-			char esc_server_name[20*2+1];
-			uint32 server_ip;
-			uint16 server_port;
-			uint16 maintenance;
-			uint16 new_;
-
-			safestrncpy(sd->userid, (char*)RFIFOP(fd,2), NAME_LENGTH);
-			safestrncpy(sd->passwd, (char*)RFIFOP(fd,26), NAME_LENGTH);
-			sd->passwdenc = 0;
-			sd->version = login_config.client_version_to_connect; // hack to skip version check
-			server_ip = ntohl(RFIFOL(fd,54));
-			server_port = ntohs(RFIFOW(fd,58));
-			safestrncpy(server_name, (char*)RFIFOP(fd,60), 20);
-			maintenance = RFIFOW(fd,82);
-			new_ = RFIFOW(fd,84);
-			RFIFOSKIP(fd,86);
-
-			Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20));
-			Sql_EscapeStringLen(sql_handle, esc_userid, sd->userid, strnlen(sd->userid, NAME_LENGTH));
-
-			ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", server_name, CONVIP(server_ip), server_port, sd->userid, sd->passwd, ip);
-
-			if( login_config.log_login && SQL_ERROR == Sql_Query(sql_handle, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s@%s','100', 'charserver - %s@%u.%u.%u.%u:%d')",
-				loginlog_db, ipl, esc_userid, esc_server_name, esc_server_name, CONVIP(server_ip), server_port) )
-				Sql_ShowDebug(sql_handle);
-
-			result = mmo_auth(sd);
-			if( result == -1 && sd->sex == 'S' && sd->account_id < MAX_SERVERS && server[sd->account_id].fd == -1 )
-			{
-				ShowStatus("Connection of the char-server '%s' accepted.\n", server_name);
-				safestrncpy(server[sd->account_id].name, server_name, sizeof(server[sd->account_id].name));
-				server[sd->account_id].fd = fd;
-				server[sd->account_id].ip = server_ip;
-				server[sd->account_id].port = server_port;
-				server[sd->account_id].users = 0;
-				server[sd->account_id].maintenance = maintenance;
-				server[sd->account_id].new_ = new_;
-
-				session[fd]->func_parse = parse_fromchar;
-				session[fd]->flag.server = 1;
-				realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK);
-
-				// send connection success
-				WFIFOHEAD(fd,3);
-				WFIFOW(fd,0) = 0x2711;
-				WFIFOB(fd,2) = 0;
-				WFIFOSET(fd,3);
-
-				// send GM account to char-server
-				send_GM_accounts(fd);
-
-				if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", sd->account_id, esc_server_name, 0) )
-					Sql_ShowDebug(sql_handle);
-			}
-			else
-			{
-				ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name);
-				WFIFOHEAD(fd,3);
-				WFIFOW(fd,0) = 0x2711;
-				WFIFOB(fd,2) = 3;
-				WFIFOSET(fd,3);
-			}
-		}
-		return 0; // processing will continue elsewhere
-
-		case 0x7530:	// Server version information request
-			ShowStatus("Sending server version information to ip: %s\n", ip);
-			RFIFOSKIP(fd,2);
-			WFIFOHEAD(fd,10);
-			WFIFOW(fd,0) = 0x7531;
-			WFIFOB(fd,2) = ATHENA_MAJOR_VERSION;
-			WFIFOB(fd,3) = ATHENA_MINOR_VERSION;
-			WFIFOB(fd,4) = ATHENA_REVISION;
-			WFIFOB(fd,5) = ATHENA_RELEASE_FLAG;
-			WFIFOB(fd,6) = ATHENA_OFFICIAL_FLAG;
-			WFIFOB(fd,7) = ATHENA_SERVER_LOGIN;
-			WFIFOW(fd,8) = ATHENA_MOD_VERSION;
-			WFIFOSET(fd,10);
-		break;
-
-		default:
-			ShowNotice("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, command);
-			set_eof(fd);
-			return 0;
-		}
-	}
-
-	RFIFOSKIP(fd,RFIFOREST(fd));
-	return 0;
-}
-
-//-----------------------
-// Console Command Parser [Wizputer]
-//-----------------------
-int parse_console(char* buf)
-{
-	char command[256];
-
-	memset(command, 0, sizeof(command));
-
-	sscanf(buf, "%[^\n]", command);
-
-	ShowInfo("Console command :%s", command);
-
-	if( strcmpi("shutdown", command) == 0 ||
-	    strcmpi("exit", command) == 0 ||
-	    strcmpi("quit", command) == 0 ||
-	    strcmpi("end", command) == 0 )
-		runflag = 0;
-	else
-	if( strcmpi("alive", command) == 0 ||
-	    strcmpi("status", command) == 0 )
-		ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n");
-	else
-	if( strcmpi("help", command) == 0 ) {
-		ShowInfo(CL_BOLD"Help of commands:"CL_RESET"\n");
-		ShowInfo("  To shutdown the server:\n");
-		ShowInfo("  'shutdown|exit|quit|end'\n");
-		ShowInfo("  To know if server is alive:\n");
-		ShowInfo("  'alive|status'\n");
-	}
-
-	return 0;
-}
-
-static int online_data_cleanup_sub(DBKey key, void *data, va_list ap)
-{
-	struct online_login_data *character= (struct online_login_data*)data;
-	if (character->char_server == -2) //Unknown server.. set them offline
-		remove_online_user(character->account_id);
-	return 0;
-}
-
-static int online_data_cleanup(int tid, unsigned int tick, int id, intptr data)
-{
-	online_db->foreach(online_db, online_data_cleanup_sub);
-	return 0;
-} 
-
-//----------------------------------
-// Reading Lan Support configuration
-//----------------------------------
-int login_lan_config_read(const char *lancfgName)
-{
-	FILE *fp;
-	int line_num = 0;
-	char line[1024], w1[64], w2[64], w3[64], w4[64];
-
-	if((fp = fopen(lancfgName, "r")) == NULL) {
-		ShowWarning("LAN Support configuration file is not found: %s\n", lancfgName);
-		return 1;
-	}
-
-	ShowInfo("Reading the configuration file %s...\n", lancfgName);
-
-	while(fgets(line, sizeof(line), fp))
-	{
-		line_num++;
-		if ((line[0] == '/' && line[1] == '/') || line[0] == '\n' || line[1] == '\n')
-			continue;
-
-		if(sscanf(line,"%[^:]: %[^:]:%[^:]:%[^\r\n]", w1, w2, w3, w4) != 4)
-		{
-			ShowWarning("Error syntax of configuration file %s in line %d.\n", lancfgName, line_num);
-			continue;
-		}
-
-		if( strcmpi(w1, "subnet") == 0 )
-		{
-			subnet[subnet_count].mask = str2ip(w2);
-			subnet[subnet_count].char_ip = str2ip(w3);
-			subnet[subnet_count].map_ip = str2ip(w4);
-
-			if( (subnet[subnet_count].char_ip & subnet[subnet_count].mask) != (subnet[subnet_count].map_ip & subnet[subnet_count].mask) )
-			{
-				ShowError("%s: Configuration Error: The char server (%s) and map server (%s) belong to different subnetworks!\n", lancfgName, w3, w4);
-				continue;
-			}
-
-			subnet_count++;
-		}
-	}
-
-	ShowStatus("Read information about %d subnetworks.\n", subnet_count);
-
-	fclose(fp);
-	return 0;
-}
-
-//-----------------------------------------------------
-// clear expired ip bans
-//-----------------------------------------------------
-int ip_ban_flush(int tid, unsigned int tick, int id, intptr data)
-{
-	if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") )
-		Sql_ShowDebug(sql_handle);
-
-	return 0;
-}
-
-//-----------------------------------
-// Reading main configuration file
-//-----------------------------------
-int login_config_read(const char* cfgName)
-{
-	char line[1024], w1[1024], w2[1024];
-	FILE* fp = fopen(cfgName, "r");
-	if (fp == NULL) {
-		ShowError("Configuration file (%s) not found.\n", cfgName);
-		return 1;
-	}
-	ShowInfo("Reading configuration file %s...\n", cfgName);
-	while(fgets(line, sizeof(line), fp))
-	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-
-		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
-			continue;
-
-		if(!strcmpi(w1,"timestamp_format"))
-			strncpy(timestamp_format, w2, 20);
-		else if(!strcmpi(w1,"stdout_with_ansisequence"))
-			stdout_with_ansisequence = config_switch(w2);
-		else if(!strcmpi(w1,"console_silent")) {
-			ShowInfo("Console Silent Setting: %d\n", atoi(w2));
-			msg_silent = atoi(w2);
-		}
-		else if( !strcmpi(w1, "bind_ip") ) {
-			char ip_str[16];
-			login_config.login_ip = host2ip(w2);
-			if( login_config.login_ip )
-				ShowStatus("Login server binding IP address : %s -> %s\n", w2, ip2str(login_config.login_ip, ip_str));
-		}
-		else if( !strcmpi(w1, "login_port") ) {
-			login_config.login_port = (uint16)atoi(w2);
-			ShowStatus("set login_port : %s\n",w2);
-		}
-		else if(!strcmpi(w1, "log_login"))
-			login_config.log_login = (bool)config_switch(w2);
-
-		else if(!strcmpi(w1, "ipban"))
-			login_config.ipban = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "dynamic_pass_failure_ban"))
-			login_config.dynamic_pass_failure_ban = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "dynamic_pass_failure_ban_interval"))
-			login_config.dynamic_pass_failure_ban_interval = atoi(w2);
-		else if(!strcmpi(w1, "dynamic_pass_failure_ban_limit"))
-			login_config.dynamic_pass_failure_ban_limit = atoi(w2);
-		else if(!strcmpi(w1, "dynamic_pass_failure_ban_duration"))
-			login_config.dynamic_pass_failure_ban_duration = atoi(w2);
-
-		else if(!strcmpi(w1, "new_account"))
-			login_config.new_account_flag = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "start_limited_time"))
-			login_config.start_limited_time = atoi(w2);
-		else if(!strcmpi(w1, "check_client_version"))
-			login_config.check_client_version = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "client_version_to_connect"))
-			login_config.client_version_to_connect = atoi(w2);
-		else if(!strcmpi(w1, "use_MD5_passwords"))
-			login_config.use_md5_passwds = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "min_level_to_connect"))
-			login_config.min_level_to_connect = atoi(w2);
-		else if(!strcmpi(w1, "date_format"))
-			safestrncpy(login_config.date_format, w2, sizeof(login_config.date_format));
-		else if(!strcmpi(w1, "console"))
-			login_config.console = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "case_sensitive"))
-			login_config.case_sensitive = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "allowed_regs")) //account flood protection system
-			allowed_regs = atoi(w2);
-		else if(!strcmpi(w1, "time_allowed"))
-			time_allowed = atoi(w2);
-		else if(!strcmpi(w1, "online_check"))
-			login_config.online_check = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "use_dnsbl"))
-			login_config.use_dnsbl = (bool)config_switch(w2);
-		else if(!strcmpi(w1, "dnsbl_servers"))
-			safestrncpy(login_config.dnsbl_servs, w2, sizeof(login_config.dnsbl_servs));
-		else if(!strcmpi(w1, "ip_sync_interval"))
-			login_config.ip_sync_interval = (unsigned int)1000*60*atoi(w2); //w2 comes in minutes.
-		else if(!strcmpi(w1, "import"))
-			login_config_read(w2);
-	}
-	fclose(fp);
-	ShowInfo("Finished reading %s.\n", cfgName);
-	return 0;
-}
-
-void sql_config_read(const char* cfgName)
-{
-	char line[1024], w1[1024], w2[1024];
-	FILE* fp = fopen(cfgName, "r");
-	if(fp == NULL) {
-		ShowError("file not found: %s\n", cfgName);
-		return;
-	}
-	ShowInfo("reading configuration file %s...\n", cfgName);
-	while(fgets(line, sizeof(line), fp))
-	{
-		if (line[0] == '/' && line[1] == '/')
-			continue;
-		if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) < 2)
-			continue;
-
-		if (!strcmpi(w1, "gm_read_method"))
-			login_config.login_gm_read = (atoi(w2) == 0);
-		else if (!strcmpi(w1, "login_db"))
-			strcpy(login_db, w2);
-		else if (!strcmpi(w1, "login_server_ip"))
-			strcpy(login_server_ip, w2);
-		else if (!strcmpi(w1, "login_server_port"))
-			login_server_port = (uint16)atoi(w2);
-		else if (!strcmpi(w1, "login_server_id"))
-			strcpy(login_server_id, w2);
-		else if (!strcmpi(w1, "login_server_pw"))
-			strcpy(login_server_pw, w2);
-		else if (!strcmpi(w1, "login_server_db"))
-			strcpy(login_server_db, w2);
-		else if (!strcmpi(w1, "default_codepage"))
-			strcpy(default_codepage, w2);
-		else if (!strcmpi(w1, "login_db_account_id"))
-			strcpy(login_db_account_id, w2);
-		else if (!strcmpi(w1, "login_db_userid"))
-			strcpy(login_db_userid, w2);
-		else if (!strcmpi(w1, "login_db_user_pass"))
-			strcpy(login_db_user_pass, w2);
-		else if (!strcmpi(w1, "login_db_level"))
-			strcpy(login_db_level, w2);
-		else if (!strcmpi(w1, "loginlog_db"))
-			strcpy(loginlog_db, w2);
-		else if (!strcmpi(w1, "reg_db"))
-			strcpy(reg_db, w2);
-		else if (!strcmpi(w1, "import"))
-			sql_config_read(w2);
-	}
-	fclose(fp);
-	ShowInfo("Done reading %s.\n", cfgName);
-}
-
-void login_set_defaults()
-{
-	login_config.login_ip = INADDR_ANY;
-	login_config.login_port = 6900;
-	login_config.ip_sync_interval = 0;
-	login_config.log_login = true;
-	safestrncpy(login_config.date_format, "%Y-%m-%d %H:%M:%S", sizeof(login_config.date_format));
-	login_config.console = false;
-	login_config.new_account_flag = true;
-	login_config.case_sensitive = true;
-	login_config.use_md5_passwds = false;
-	login_config.login_gm_read = true;
-	login_config.min_level_to_connect = 0;
-	login_config.online_check = true;
-	login_config.check_client_version = false;
-	login_config.client_version_to_connect = 20;
-
-	login_config.ipban = true;
-	login_config.dynamic_pass_failure_ban = true;
-	login_config.dynamic_pass_failure_ban_interval = 5;
-	login_config.dynamic_pass_failure_ban_limit = 7;
-	login_config.dynamic_pass_failure_ban_duration = 5;
-	login_config.use_dnsbl = false;
-	safestrncpy(login_config.dnsbl_servs, "", sizeof(login_config.dnsbl_servs));
-}
-
-//--------------------------------------
-// Function called at exit of the server
-//--------------------------------------
-void do_final(void)
-{
-	int i, fd;
-	ShowStatus("Terminating...\n");
-
-	mmo_db_close();
-	online_db->destroy(online_db, NULL);
-	auth_db->destroy(auth_db, NULL);
-
-	if(gm_account_db) aFree(gm_account_db);
-
-	for (i = 0; i < MAX_SERVERS; i++) {
-		if ((fd = server[i].fd) >= 0) {
-			memset(&server[i], 0, sizeof(struct mmo_char_server));
-			server[i].fd = -1;
-			do_close(fd);
-		}
-	}
-	do_close(login_fd);
-
-	ShowStatus("Finished.\n");
-}
-
-//------------------------------
-// Function called when the server
-// has received a crash signal.
-//------------------------------
-void do_abort(void)
-{
-}
-
-void set_server_type(void)
-{
-	SERVER_TYPE = ATHENA_SERVER_LOGIN;
-}
-
-//------------------------------
-// Login server initialization
-//------------------------------
-int do_init(int argc, char** argv)
-{
-	int i;
-
-	login_set_defaults();
-
-	// read login-server configuration
-	login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
-	sql_config_read(SQL_CONF_NAME);
-	login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME);
-
-	srand((unsigned int)time(NULL));
-
-	for( i = 0; i < MAX_SERVERS; i++ )
-		server[i].fd = -1;
-
-	// Online user database init
-	online_db = idb_alloc(DB_OPT_RELEASE_DATA);
-	add_timer_func_list(waiting_disconnect_timer, "waiting_disconnect_timer");
-
-	// Auth init
-	auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
-	mmo_auth_sqldb_init();
-
-	// Read account information.
-	if(login_config.login_gm_read)
-		read_gm_account();
-
-	// set default parser as parse_login function
-	set_defaultparse(parse_login);
-
-	// ban deleter timer
-	add_timer_func_list(ip_ban_flush, "ip_ban_flush");
-	add_timer_interval(gettick()+10, ip_ban_flush, 0, 0, 60*1000);
-
-	// every 10 minutes cleanup online account db.
-	add_timer_func_list(online_data_cleanup, "online_data_cleanup");
-	add_timer_interval(gettick() + 600*1000, online_data_cleanup, 0, 0, 600*1000);
-
-	// add timer to detect ip address change and perform update
-	if (login_config.ip_sync_interval) {
-		add_timer_func_list(sync_ip_addresses, "sync_ip_addresses");
-		add_timer_interval(gettick() + login_config.ip_sync_interval, sync_ip_addresses, 0, 0, login_config.ip_sync_interval);
-	}
-
-	if( login_config.console )
-	{
-		//##TODO invoke a CONSOLE_START plugin event
-	}
-
-	new_reg_tick = gettick();
-
-	// server port open & binding
-	login_fd = make_listen_bind(login_config.login_ip, login_config.login_port);
-
-	ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port);
-
-	return 0;
-}

+ 0 - 94
src/login_sql/login.h

@@ -1,94 +0,0 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
-
-#ifndef _LOGIN_SQL_H_
-#define _LOGIN_SQL_H_
-
-#include "../common/mmo.h" // NAME_LENGTH
-
-#define LOGIN_CONF_NAME	"conf/login_athena.conf"
-#define SQL_CONF_NAME "conf/inter_athena.conf"
-#define LAN_CONF_NAME "conf/subnet_athena.conf"
-
-// supported encryption types: 1- passwordencrypt, 2- passwordencrypt2, 3- both
-#define PASSWORDENC 3
-
-struct login_session_data {
-
-	int account_id;
-	long login_id1;
-	long login_id2;
-	char sex;
-
-	char userid[NAME_LENGTH];
-	char passwd[NAME_LENGTH];
-	int passwdenc;
-	char md5key[20];
-	uint16 md5keylen;
-
-	char lastlogin[24];
-	uint8 level;
-	int version;
-
-	int fd;
-};
-
-struct mmo_char_server {
-	char name[20];
-	int fd;
-	uint32 ip;
-	uint16 port;
-	int users;
-	int maintenance;
-	int new_;
-};
-
-struct Login_Config {
-
-	uint32 login_ip;                                // the address to bind to
-	uint16 login_port;                              // the port to bind to
-	unsigned int ip_sync_interval;                  // interval (in minutes) to execute a DNS/IP update (for dynamic IPs)
-	bool log_login;                                 // whether to log login server actions or not
-	char date_format[32];                           // date format used in messages
-	bool console;                                   // console input system enabled?
-	bool new_account_flag;                          // autoregistration via _M/_F ?
-	int start_limited_time;                         // new account expiration time (-1: unlimited)
-	bool case_sensitive;                            // are logins case sensitive ?
-	bool use_md5_passwds;                           // work with password hashes instead of plaintext passwords?
-	bool login_gm_read;                             // should the login server handle info about gm accounts?
-	int min_level_to_connect;                       // minimum level of player/GM (0: player, 1-99: GM) to connect
-	bool online_check;                              // reject incoming players that are already registered as online ?
-	bool check_client_version;                      // check the clientversion set in the clientinfo ?
-	int client_version_to_connect;                  // the client version needed to connect (if checking is enabled)
-
-	bool ipban;                                     // perform IP blocking (via contents of `ipbanlist`) ?
-	bool dynamic_pass_failure_ban;                  // automatic IP blocking due to failed login attemps ?
-	unsigned int dynamic_pass_failure_ban_interval; // how far to scan the loginlog for password failures
-	unsigned int dynamic_pass_failure_ban_limit;    // number of failures needed to trigger the ipban
-	unsigned int dynamic_pass_failure_ban_duration; // duration of the ipban
-	bool use_dnsbl;                                 // dns blacklist blocking ?
-	char dnsbl_servs[1024];                         // comma-separated list of dnsbl servers
-
-};
-
-struct mmo_account {
-
-	int account_id;
-	char sex;
-	char userid[24];
-	char pass[32+1]; // 23+1 for normal, 32+1 for md5-ed passwords
-	char lastlogin[24];
-	int logincount;
-	uint32 state; // packet 0x006a value + 1 (0: compte OK)
-	char email[40]; // e-mail (by default: a@a.com)
-	char error_message[20]; // Message of error code #6 = Your are Prohibited to log in until %s (packet 0x006a)
-	time_t unban_time; // # of seconds 1/1/1970 (timestamp): ban time limit of the account (0 = no ban)
-	time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited)
-	char last_ip[16]; // save of last IP of connection
-	char memo[255]; // a memo field
-	int account_reg2_num;
-	struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server)
-};
-
-
-#endif /* _LOGIN_SQL_H_ */

+ 2 - 16
src/map/atcommand.c

@@ -4187,19 +4187,6 @@ int atcommand_reloadscript(const int fd, struct map_session_data* sd, const char
 	return 0;
 }
 
-/*==========================================
- * @reloadgmdb - reloads gm levels from where they are stored (gm_account.txt / mysql database)
- *------------------------------------------*/
-int atcommand_reloadgmdb(const int fd, struct map_session_data* sd, const char* command, const char* message)
-{
-	nullpo_retr(-1, sd);
-	chrif_reloadGMdb();
-
-	clif_displaymessage(fd, msg_txt(101)); // Login-server asked to reload GM accounts and their level.
-
-	return 0;
-}
-
 /*==========================================
  * @mapinfo <map name> [0-3] by MC_Cameri
  * => Shows information about the map [map name]
@@ -6632,7 +6619,7 @@ int atcommand_adjgmlvl(const int fd, struct map_session_data* sd, const char* co
 		return -1;
 	}
 
-    pc_set_gm_level(pl_sd->status.account_id, newlev);
+	sd->gmlevel = newlev;
 
     return 0;
 }
@@ -8191,7 +8178,7 @@ int atcommand_request(const int fd, struct map_session_data* sd, const char* com
 	}
 
 	sprintf(atcmd_output, msg_txt(278), message);	// (@request): %s
-	intif_wis_message_to_gm(sd->status.name, lowest_gm_level, atcmd_output);
+	intif_wis_message_to_gm(sd->status.name, battle_config.lowest_gm_level, atcmd_output);
 	clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
 	clif_displaymessage(sd->fd,msg_txt(279));	// @request sent.
 	return 0;
@@ -8400,7 +8387,6 @@ AtCommandInfo atcommand_info[] = {
 	{ "reloadmobdb",       99,     atcommand_reloadmobdb },
 	{ "reloadskilldb",     99,     atcommand_reloadskilldb },
 	{ "reloadscript",      99,     atcommand_reloadscript },
-	{ "reloadgmdb",        99,     atcommand_reloadgmdb },
 	{ "reloadatcommand",   99,     atcommand_reloadatcommand },
 	{ "reloadbattleconf",  99,     atcommand_reloadbattleconf },
 	{ "reloadstatusdb",    99,     atcommand_reloadstatusdb },

+ 1 - 0
src/map/battle.c

@@ -3395,6 +3395,7 @@ static const struct _battle_data {
 	{ "guild_max_castles",                  &battle_config.guild_max_castles,               0,      0,      INT_MAX,        },
 	{ "guild_skill_relog_delay",            &battle_config.guild_skill_relog_delay,         0,      0,      1,              },
 	{ "emergency_call",                     &battle_config.emergency_call,                  11,     0,      31,             },
+	{ "lowest_gm_level",                    &battle_config.lowest_gm_level,                 1,      0,      99,             },
 	{ "atcommand_gm_only",                  &battle_config.atc_gmonly,                      0,      0,      1,              },
 	{ "atcommand_spawn_quantity_limit",     &battle_config.atc_spawn_quantity_limit,        100,    0,      INT_MAX,        },
 	{ "atcommand_slave_clone_limit",        &battle_config.atc_slave_clone_limit,           25,     0,      INT_MAX,        },

+ 1 - 0
src/map/battle.h

@@ -141,6 +141,7 @@ extern struct Battle_Config
 	int monster_max_aspd;
 	int view_range_rate;
 	int chase_range_rate;
+	int lowest_gm_level;
 	int atc_gmonly;
 	int atc_spawn_quantity_limit;
 	int atc_slave_clone_limit;

+ 53 - 74
src/map/chrif.c

@@ -36,7 +36,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
 	60, 3,-1,27,10,-1, 6,-1,	// 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
 	 6,-1,18, 7,-1,35,30,-1,	// 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, F->2b07
 	 6,30,-1,-1,86, 7,44,34,	// 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
-	11,10,10, 6,11,-1,266,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, U->2b15, U->2b16, U->2b17
+	11,10,10, 6,11,-1,266,10,	// 2b10-2b17: U->2b10, U->2b11, U->2b12, U->2b13, U->2b14, F->2b15, U->2b16, U->2b17
 	 2,10, 2,-1,-1,-1, 2, 7,	// 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
 	-1,10, 8, 2, 2,14,19,19,	// 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
 };
@@ -71,7 +71,7 @@ static const int packet_len_table[0x3d] = { // U - used, F - free
 //2b12: Incoming, chrif_divorceack -> 'divorce chars
 //2b13: Incoming, chrif_accountdeletion -> 'Delete acc XX, if the player is on, kick ....'
 //2b14: Incoming, chrif_accountban -> 'not sure: kick the player with message XY'
-//2b15: Incoming, chrif_recvgmaccounts -> 'receive gm accs from charserver (seems to be incomplete !)'
+//2b15: FREE
 //2b16: Outgoing, chrif_ragsrvinfo -> 'sends motd / rates ....'
 //2b17: Outgoing, chrif_char_offline -> 'tell the charserver that the char is now offline'
 //2b18: Outgoing, chrif_char_reset_offline -> 'set all players OFF!'
@@ -512,56 +512,58 @@ int chrif_scdata_request(int account_id, int char_id)
 }
 
 /*==========================================
- * new auth system [Kevin]
+ * Request auth confirmation
  *------------------------------------------*/
 void chrif_authreq(struct map_session_data *sd)
 {
 	struct auth_node *node= chrif_search(sd->bl.id);
 
-	if(!node) {
-		//request data from char server and store current auth info
-		WFIFOHEAD(char_fd,19);
-		WFIFOW(char_fd,0) = 0x2b26;
-		WFIFOL(char_fd,2) = sd->status.account_id;
-		WFIFOL(char_fd,6) = sd->status.char_id;
-		WFIFOL(char_fd,10) = sd->login_id1;
-		WFIFOB(char_fd,14) = sd->status.sex;
-		WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr);
-		WFIFOSET(char_fd,19);
-		chrif_sd_to_auth(sd, ST_LOGIN);
+	if( node != NULL )
+	{
+		set_eof(sd->fd);
 		return;
-	} else {	//char already online? kick connect request and tell char server that this person is online
-					//This case shouldn't happen in an ideal system
-		pc_authfail(sd);
-		chrif_char_online(sd);
 	}
-	return;
+
+	WFIFOHEAD(char_fd,19);
+	WFIFOW(char_fd,0) = 0x2b26;
+	WFIFOL(char_fd,2) = sd->status.account_id;
+	WFIFOL(char_fd,6) = sd->status.char_id;
+	WFIFOL(char_fd,10) = sd->login_id1;
+	WFIFOB(char_fd,14) = sd->status.sex;
+	WFIFOL(char_fd,15) = htonl(session[sd->fd]->client_addr);
+	WFIFOSET(char_fd,19);
+	chrif_sd_to_auth(sd, ST_LOGIN);
 }
 
-//character selected, insert into auth db
+/*==========================================
+ * Auth confirmation ack
+ *------------------------------------------*/
 void chrif_authok(int fd)
 {
 	int account_id;
 	uint32 login_id1;
-	time_t expiration_time;
 	uint32 login_id2;
+	time_t expiration_time;
+	int gmlevel;
 	struct mmo_charstatus* status;
 	int char_id;
 	struct auth_node *node;
 	TBL_PC* sd;
 
 	//Check if both servers agree on the struct's size
-	if( RFIFOW(fd,2) - 20 != sizeof(struct mmo_charstatus) )
+	if( RFIFOW(fd,2) - 24 != sizeof(struct mmo_charstatus) )
 	{
-		ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 20, sizeof(struct mmo_charstatus));
+		ShowError("chrif_authok: Data size mismatch! %d != %d\n", RFIFOW(fd,2) - 24, sizeof(struct mmo_charstatus));
 		return;
 	}
 
 	account_id = RFIFOL(fd,4);
 	login_id1 = RFIFOL(fd,8);
-	expiration_time = (time_t)(int32)RFIFOL(fd,12);
-	login_id2 = RFIFOL(fd,16);
-	status = (struct mmo_charstatus*)RFIFOP(fd,20);
+	login_id2 = RFIFOL(fd,12);
+	expiration_time = (time_t)(int32)RFIFOL(fd,16);
+	gmlevel = RFIFOL(fd,20);
+	status = (struct mmo_charstatus*)RFIFOP(fd,24);
+
 	char_id = status->char_id;
 
 	//Check if we don't already have player data in our server
@@ -569,33 +571,35 @@ void chrif_authok(int fd)
 	if ((sd = map_id2sd(account_id)) != NULL)
 		return;
 	
-	if ((node = chrif_search(account_id)))
-	{	//Is the character already awaiting authorization?
-		if (node->state != ST_LOGIN)
-			return; //character in logout phase, do not touch that data.
-		if (node->sd)
-		{
-			sd = node->sd;
-			if(node->char_dat == NULL &&
-				node->account_id == account_id &&
-				node->char_id == char_id &&
-				node->login_id1 == login_id1 )
-			{ //Auth Ok
-				if (pc_authok(sd, login_id2, expiration_time, status))
-				{
-					return;
-				}
-			} else { //Auth Failed
-				pc_authfail(sd);
-			}
-			chrif_char_offline(sd); //Set client offline
-			chrif_auth_delete(account_id, char_id, ST_LOGIN);
-			return;
-		}
+	if ((node = chrif_search(account_id)) == NULL)
+		return; // should not happen
+
+	if (node->state != ST_LOGIN)
+		return; //character in logout phase, do not touch that data.
+
+	if (node->sd == NULL)
+	{
+		/*
 		//When we receive double login info and the client has not connected yet,
 		//discard the older one and keep the new one.
 		chrif_auth_delete(node->account_id, node->char_id, ST_LOGIN);
+		*/
+		return; // should not happen
+	}
+
+	sd = node->sd;
+	if(node->char_dat == NULL &&
+		node->account_id == account_id &&
+		node->char_id == char_id &&
+		node->login_id1 == login_id1 )
+	{ //Auth Ok
+		if (pc_authok(sd, login_id2, expiration_time, gmlevel, status))
+			return;
+	} else { //Auth Failed
+		pc_authfail(sd);
 	}
+	chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already.
+	chrif_auth_delete(account_id, char_id, ST_LOGIN);
 }
 
 // client authentication failed
@@ -1035,30 +1039,6 @@ int chrif_disconnectplayer(int fd)
 	return 0;
 }
 
-/*==========================================
- * Request to reload GM accounts and their levels: send to char-server by [Yor]
- *------------------------------------------*/
-int chrif_reloadGMdb(void)
-{
-	chrif_check(-1);
-
-	WFIFOHEAD(char_fd,2);
-	WFIFOW(char_fd,0) = 0x2af7;
-	WFIFOSET(char_fd,2);
-
-	return 0;
-}
-
-/*==========================================
- * Receiving GM accounts and their levels from char-server by [Yor]
- *------------------------------------------*/
-int chrif_recvgmaccounts(int fd)
-{
-	int nAccounts = pc_read_gm_account(fd);
-	ShowInfo("From login-server: receiving information of '"CL_WHITE"%d"CL_RESET"' GM accounts.\n", nAccounts);
-	return 0;
-}
-
 /*==========================================
  * Request/Receive top 10 Fame character list
  *------------------------------------------*/
@@ -1454,7 +1434,6 @@ int chrif_parse(int fd)
 		case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break;
 		case 0x2b13: chrif_accountdeletion(fd); break;
 		case 0x2b14: chrif_accountban(fd); break;
-		case 0x2b15: chrif_recvgmaccounts(fd); break;
 		case 0x2b1b: chrif_recvfamelist(fd); break;
 		case 0x2b1d: chrif_load_scdata(fd); break;
 		case 0x2b1e: chrif_update_ip(fd); break;

+ 0 - 1
src/map/chrif.h

@@ -44,7 +44,6 @@ int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port);
 int chrif_searchcharid(int char_id);
 int chrif_changeemail(int id, const char *actual_email, const char *new_email);
 int chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second);
-int chrif_reloadGMdb(void);
 int chrif_updatefamelist(struct map_session_data *sd);
 int chrif_buildfamelist(void);
 int chrif_save_scdata(struct map_session_data *sd);

+ 2 - 42
src/map/map.c

@@ -79,8 +79,6 @@ Sql* logmysql_handle;
 
 #endif /* not TXT_ONLY */
 
-int lowest_gm_level = 1;
-
 // This param using for sending mainchat
 // messages like whispers to this nick. [LuzZza]
 char main_chat_nick[16] = "Main";
@@ -2955,13 +2953,8 @@ int inter_config_read(char *cfgName)
 		i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
 		if(i!=2)
 			continue;
-		if(strcmpi(w1,"party_share_level")==0){
-			party_share_level = config_switch(w2);
-		} else if(strcmpi(w1,"lowest_gm_level")==0){
-			lowest_gm_level = atoi(w2);
-		
-		/* Main chat nick [LuzZza] */
-		} else if(strcmpi(w1, "main_chat_nick")==0){
+
+		if(strcmpi(w1, "main_chat_nick")==0){
 			strcpy(main_chat_nick, w2);
 			
 	#ifndef TXT_ONLY
@@ -3068,37 +3061,6 @@ int log_sql_init(void)
 	return 0;
 }
 
-/*=============================================
- * Does a mysql_ping to all connection handles
- *---------------------------------------------*/
-int map_sql_ping(int tid, unsigned int tick, int id, intptr data) 
-{
-	ShowInfo("Pinging SQL server to keep connection alive...\n");
-	Sql_Ping(mmysql_handle);
-	if (log_config.sql_logs)
-		Sql_Ping(logmysql_handle);
-	return 0;
-}
-
-int sql_ping_init(void)
-{
-	uint32 connection_timeout, connection_ping_interval;
-
-	// set a default value
-	connection_timeout = 28800; // 8 hours
-
-	// ask the mysql server for the timeout value
-	Sql_GetTimeout(mmysql_handle, &connection_timeout);
-	if (connection_timeout < 60)
-		connection_timeout = 60;
-
-	// establish keepalive
-	connection_ping_interval = connection_timeout - 30; // 30-second reserve
-	add_timer_func_list(map_sql_ping, "map_sql_ping");
-	add_timer_interval(gettick() + connection_ping_interval*1000, map_sql_ping, 0, 0, connection_ping_interval*1000);
-
-	return 0;
-}
 #endif /* not TXT_ONLY */
 
 int map_db_final(DBKey k,void *d,va_list ap)
@@ -3436,8 +3398,6 @@ int do_init(int argc, char *argv[])
 #ifndef TXT_ONLY /* mail system [Valaris] */
 	if (log_config.sql_logs)
 		log_sql_init();
-
-	sql_ping_init();
 #endif /* not TXT_ONLY */
 
 	npc_event_do_oninit();	// npc‚ÌOnInitƒCƒxƒ“ƒg?�s

+ 0 - 1
src/map/map.h

@@ -633,7 +633,6 @@ typedef struct homun_data       TBL_HOM;
 	( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) )
 
 
-extern int lowest_gm_level;
 extern char main_chat_nick[16];
 
 #ifndef TXT_ONLY

+ 1 - 1
src/map/npc_chat.c

@@ -14,7 +14,7 @@
 #include "pc.h" // struct map_session_data
 #include "script.h" // set_var()
 
-#include "pcre.h"
+#include <pcre.h>
 
 #include <stdio.h>
 #include <stdlib.h>

+ 0 - 1
src/map/party.c

@@ -28,7 +28,6 @@
 
 
 static DBMap* party_db; // int party_id -> struct party_data*
-int party_share_level = 10;
 int party_send_xy_timer(int tid, unsigned int tick, int id, intptr data);
 
 /*==========================================

+ 0 - 2
src/map/party.h

@@ -31,8 +31,6 @@ struct party_data {
 };
 
 
-extern int party_share_level;
-
 void do_init_party(void);
 void do_final_party(void);
 struct party_data* party_search(int party_id);

+ 4 - 50
src/map/pc.c

@@ -6,7 +6,7 @@
 #include "../common/malloc.h"
 #include "../common/nullpo.h"
 #include "../common/showmsg.h"
-#include "../common/socket.h" // RFIFO*()
+#include "../common/socket.h" // session[]
 #include "../common/strlib.h" // safestrncpy()
 #include "../common/timer.h"
 #include "../common/utils.h"
@@ -58,9 +58,6 @@ struct fame_list taekwon_fame_list[MAX_FAME_LIST];
 
 static unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_AMMO};
 
-static struct gm_account *gm_account = NULL;
-static int GM_num = 0;
-
 #define MOTD_LINE_SIZE 128
 char motd_text[MOTD_LINE_SIZE][256]; // Message of the day buffer [Valaris]
 
@@ -85,34 +82,7 @@ int pc_class2idx(int class_) {
 
 int pc_isGM(struct map_session_data* sd)
 {
-	int i;
-	nullpo_retr(0, sd);
-
-	if( sd->bl.type != BL_PC )
-		return 99;
-
-	ARR_FIND( 0, GM_num, i, gm_account[i].account_id == sd->status.account_id );
-	return ( i < GM_num ) ? gm_account[i].level : 0;
-}
-
-int pc_set_gm_level(int account_id, int level)
-{
-    int i;
-
-	ARR_FIND( 0, GM_num, i, account_id == gm_account[i].account_id );
-	if( i < GM_num )
-	{
-		gm_account[i].level = level;
-	}
-	else
-	{
-	    gm_account = (struct gm_account *) aRealloc(gm_account, (GM_num + 1) * sizeof(struct gm_account));
-	    gm_account[GM_num].account_id = account_id;
-	    gm_account[GM_num].level = level;
-	    GM_num++;
-	}
-
-	return 0;
+	return sd->gmlevel;
 }
 
 static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr data)
@@ -709,12 +679,13 @@ int pc_isequip(struct map_session_data *sd,int n)
  * session idに問題無し
  * char鯖から送られてきたステ?タスを設定
  *------------------------------------------*/
-bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, struct mmo_charstatus *st)
+bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int gmlevel, struct mmo_charstatus *st)
 {
 	int i;
 	unsigned long tick = gettick();
 
 	sd->login_id2 = login_id2;
+	sd->gmlevel = gmlevel;
 	memcpy(&sd->status, st, sizeof(*st));
 
 	if (st->sex != sd->status.sex) {
@@ -6925,21 +6896,6 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr data)
 	return 0;
 }
 
-int pc_read_gm_account(int fd)
-{
-	//FIXME: this implementation is a total failure (direct reading from RFIFO) [ultramage]
-	int i = 0;
-	if (gm_account != NULL)
-		aFree(gm_account);
-	GM_num = 0;
-	gm_account = (struct gm_account *) aMallocA(((RFIFOW(fd,2) - 4) / 5)*sizeof(struct gm_account));
-	for (i = 4; i < RFIFOW(fd,2); i += 5) {
-		gm_account[GM_num].account_id = RFIFOL(fd,i);
-		gm_account[GM_num].level = (int)RFIFOB(fd,i+4);
-		GM_num++;
-	}
-	return GM_num;
-}
 static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap)
 {
 	if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled)
@@ -7487,8 +7443,6 @@ int pc_read_motd(void)
  *------------------------------------------*/
 void do_final_pc(void)
 {
-	if (gm_account)
-		aFree(gm_account);
 	return;
 }
 

+ 2 - 3
src/map/pc.h

@@ -130,6 +130,7 @@ struct map_session_data {
 	} special_state;
 	int login_id1, login_id2;
 	unsigned short class_;	//This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
+	int gmlevel;
 
 	int packet_ver;  // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18
 	struct mmo_charstatus status;
@@ -498,7 +499,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type);
 int pc_makesavestatus(struct map_session_data *);
 void pc_respawn(struct map_session_data* sd, uint8 clrtype);
 int pc_setnewpc(struct map_session_data*,int,int,int,unsigned int,int,int);
-bool pc_authok(struct map_session_data*, int, time_t, struct mmo_charstatus *);
+bool pc_authok(struct map_session_data* sd, int, time_t, int gmlevel, struct mmo_charstatus* status);
 void pc_authfail(struct map_session_data *);
 int pc_reg_received(struct map_session_data *sd);
 
@@ -655,7 +656,6 @@ struct map_session_data *pc_get_child(struct map_session_data *sd);
 void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick);
 void pc_regen (struct map_session_data *sd, unsigned int diff_tick);
 
-int pc_set_gm_level(int account_id, int level);
 void pc_setstand(struct map_session_data *sd);
 int pc_candrop(struct map_session_data *sd,struct item *item);
 
@@ -685,7 +685,6 @@ struct sg_data {
 };
 extern const struct sg_data sg_info[3];
 
-int pc_read_gm_account(int fd);
 void pc_setinvincibletimer(struct map_session_data* sd, int val);
 void pc_delinvincibletimer(struct map_session_data* sd);
 

+ 2 - 2
src/map/trade.c

@@ -70,7 +70,7 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
 	} 
 	
 	//Fixed. Only real GMs can request trade from far away! [Lupus] 
-	if (level < lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
+	if (level < battle_config.lowest_gm_level && (sd->bl.m != target_sd->bl.m ||
 		!check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE)
 	)) {
 		clif_tradestart(sd, 0); // too far
@@ -127,7 +127,7 @@ void trade_tradeack(struct map_session_data *sd, int type)
 		return; //If client didn't send accept, it's a broken packet?
 
 	//Copied here as well since the original character could had warped.
-	if (pc_isGM(tsd) < lowest_gm_level && (sd->bl.m != tsd->bl.m ||
+	if (pc_isGM(tsd) < battle_config.lowest_gm_level && (sd->bl.m != tsd->bl.m ||
 		!check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE)
 	)) {
 		clif_tradestart(sd, 0); // too far

+ 0 - 0
src/mysql/mysql-5.0.20


+ 41 - 164
src/txt-converter/login-converter.c

@@ -1,157 +1,50 @@
 // (c) eAthena Dev Team - Licensed under GNU GPL
 // For more information, see LICENCE in the main folder
 
+#define WITH_TXT
+#define WITH_SQL
+
 #include "../common/cbasetypes.h"
-#include "../common/mmo.h"
+#include "../common/mmo.h" // struct mmo_account
 #include "../common/core.h"
-#include "../common/db.h"
 #include "../common/showmsg.h"
-#include "../common/sql.h"
-#include "../common/malloc.h"
-
+#include "../login/account.h"
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
-char login_account_id[256]="account_id";
-char login_userid[256]="userid";
-char login_user_pass[256]="user_pass";
-char login_db[256]="login";
-char globalreg_db[256]="global_reg_value";
-
-static DBMap* gm_account_db=NULL; // int account_id -> struct gm_account*
+#define LOGIN_CONF_NAME "conf/login_athena.conf"
 
-int db_server_port = 3306;
-char db_server_ip[32] = "127.0.0.1";
-char db_server_id[32] = "ragnarok";
-char db_server_pw[32] = "ragnarok";
-char db_server_logindb[32] = "ragnarok";
+AccountDB* txtdb = NULL;
+AccountDB* sqldb = NULL;
 
-#define INTER_CONF_NAME "conf/inter_athena.conf"
-#define GM_ACCOUNT_NAME "conf/GM_account.txt"
-#define ACCOUNT_TXT_NAME "save/account.txt"
 //--------------------------------------------------------
 
-int isGM(int account_id)
-{
-	struct gm_account* p = (struct gm_account*)idb_get(gm_account_db,account_id);
-	return( p != NULL ) ? p->level : 0;
-}
-
-int read_gm_account()
-{
-	char line[8192];
-	struct gm_account *p;
-	FILE *fp;
-	int line_counter = 0, gm_counter = 0;
-	
-	ShowStatus("Starting reading gm_account\n");
-	
-	if( (fp = fopen(GM_ACCOUNT_NAME,"r")) == NULL )
-		return 1;
-	
-	gm_account_db = idb_alloc(DB_OPT_RELEASE_DATA);
-	
-	while(fgets(line,sizeof(line),fp))
-	{
-		line_counter++;
-		if ((line[0] == '/' && line[1] == '/') || line[0] == '\0' || line[0] == '\n' || line[0] == '\r')
-			continue;
-		
-		p = (struct gm_account*)aMalloc(sizeof(struct gm_account));
-		if(p==NULL){
-			ShowFatalError("gm_account: out of memory!\n");
-			exit(EXIT_FAILURE);
-		}
-		
-		if(sscanf(line,"%d %d",&p->account_id,&p->level) != 2 || p->level <= 0) {
-			ShowWarning("gm_account: unsupported data format [conf/GM_account.txt] on line %d\n", line_counter);
-			continue;
-		}
-		else {
-			if(p->level > 99)
-				p->level = 99;
-			p = (struct gm_account*)idb_put(gm_account_db,p->account_id,p);
-			if( p )
-				aFree(p);// old entry replaced
-			gm_counter++;
-			ShowInfo("GM ID: %d Level: %d\n",p->account_id,p->level);
-		}
-	}
-
-	fclose(fp);
-	ShowStatus("%d ID of gm_accounts read.\n", gm_counter);
-	return 0;
-}
-
 int convert_login(void)
 {
-	Sql* mysql_handle;
-	SqlStmt* stmt;
-	int line_counter = 0;
-	FILE *fp;
-	int account_id, logincount, user_level, state, n, i;
-	char line[2048], userid[2048], pass[2048], lastlogin[2048], sex, email[2048], error_message[2048], last_ip[2048], memo[2048];
-	int unban_time, expiration_time;
-	char dummy[2048];
+	AccountDBIterator* iter;
+	struct mmo_account acc;
 
-	mysql_handle = Sql_Malloc();
-	if ( SQL_ERROR == Sql_Connect(mysql_handle, db_server_id, db_server_pw, db_server_ip, db_server_port, db_server_logindb) )
+	if( !txtdb->init(txtdb) || !sqldb->init(sqldb) )
 	{
-		Sql_ShowDebug(mysql_handle);
-		Sql_Free(mysql_handle);
-		exit(EXIT_FAILURE);
-	}
-	ShowStatus("Connect: Success!\n");
-	
-	ShowStatus("Convert start...\n");
-	fp = fopen(ACCOUNT_TXT_NAME,"r");
-	if(fp == NULL)
+		ShowFatalError("Initialization failed, unable to start conversion.\n");
 		return 0;
+	}
 
-	while(fgets(line,sizeof(line),fp) != NULL)
-	{
-		line_counter++;
-		if(line[0]=='/' && line[1]=='/')
-			continue;
-
-		i = sscanf(line, "%d\t%[^\t]\t%[^\t]\t%[^\t]\t%c\t%d\t%d\t%[^\t]\t%[^\t]\t%d\t%[^\t]\t%[^\t]\t%d\t%[^\r\n]%n",
-			&account_id, userid, pass, lastlogin, &sex, &logincount, &state,
-			email, error_message, &expiration_time, last_ip, memo, &unban_time, dummy, &n);
+	ShowStatus("Conversion started...\n");
+	//TODO: do some counting & statistics
 
-		if (i < 13) {
-			ShowWarning("Skipping incompatible data on line %d\n", line_counter);
-			continue;
- 		}
-
-		if (i > 13)
-			ShowWarning("Reading login account variables is not implemented, data will be lost! (line %d)\n", line_counter);
-
-		user_level = isGM(account_id);
-		ShowInfo("Converting user (id: %d, name: %s, gm level: %d)\n", account_id, userid, user_level);
-		
-		stmt = SqlStmt_Malloc(mysql_handle);
-		if( SQL_ERROR == SqlStmt_Prepare(stmt, 
-			"REPLACE INTO `login` "
-			"(`account_id`, `userid`, `user_pass`, `lastlogin`, `sex`, `logincount`, `email`, `level`, `error_message`, `expiration_time`, `last_ip`, `memo`, `unban_time`, `state`) "
-			"VALUES "
-			"(%d, ?, ?, '%s', '%c', %d, '%s', %d, '%s', %d, '%s', '%s', %d, %d)",
-			account_id, lastlogin, sex, logincount, email, user_level, error_message, expiration_time, last_ip, memo, unban_time, state)
-		||	SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_STRING, userid, strnlen(userid, 255))
-		||	SQL_ERROR == SqlStmt_BindParam(stmt, 1, SQLDT_STRING, pass, strnlen(pass, 32))
-		||	SQL_ERROR == SqlStmt_Execute(stmt) )
-		{
-			SqlStmt_ShowDebug(stmt);
-		}
-		SqlStmt_Free(stmt);
-	
-		//TODO: parse the rest of the line to read the login-stored account variables, and import them to `global_reg_value`
-		//      then remove the 'dummy' buffer
+	iter = txtdb->iterator(txtdb);
+	while( iter->next(iter, &acc) )
+	{
+		ShowInfo("Converting user (id: %d, name: %s, gm level: %d)...", acc.account_id, acc.userid, acc.level);
+		if( sqldb->create(sqldb, &acc) )
+			ShowMessage(CL_GREEN "success.\n");
+		else
+			ShowMessage(CL_RED "failed!\n");
 	}
-	fclose(fp);
-	Sql_Free(mysql_handle);
+	iter->destroy(iter);
 
-	ShowStatus("Convert end...\n");
+	ShowStatus("Conversion finished.\n");
 
 	return 0;
 }
@@ -162,7 +55,7 @@ int login_config_read(const char* cfgName)
 	char line[1024], w1[1024], w2[1024];
 	FILE *fp;
 
-	ShowStatus("Start reading interserver configuration: %s\n", cfgName);
+	ShowStatus("Start reading login server configuration: %s\n", cfgName);
 
 	fp=fopen(cfgName,"r");
 	if(fp==NULL){
@@ -179,56 +72,40 @@ int login_config_read(const char* cfgName)
 		if(i!=2)
 			continue;
 
-		//add for DB connection
-		if(strcmpi(w1,"db_server_ip")==0){
-			strcpy(db_server_ip, w2);
-			ShowStatus("set db_server_ip : %s\n",w2);
-		}
-		else if(strcmpi(w1,"db_server_port")==0){
-			db_server_port=atoi(w2);
-			ShowStatus("set db_server_port : %s\n",w2);
-		}
-		else if(strcmpi(w1,"db_server_id")==0){
-			strcpy(db_server_id, w2);
-			ShowStatus("set db_server_id : %s\n",w2);
-		}
-		else if(strcmpi(w1,"db_server_pw")==0){
-			strcpy(db_server_pw, w2);
-			ShowStatus("set db_server_pw : %s\n",w2);
-		}
-		else if(strcmpi(w1,"db_server_logindb")==0){
-			strcpy(db_server_logindb, w2);
-			ShowStatus("set db_server_logindb : %s\n",w2);
-		}
+		txtdb->set_property(txtdb, w1, w2);
+		sqldb->set_property(sqldb, w1, w2);
+
 		//support the import command, just like any other config
-		else if(strcmpi(w1,"import")==0){
+		if( strcmpi(w1,"import") == 0 )
 			login_config_read(w2);
-		}
 	}
+
 	fclose(fp);
-	ShowStatus("End reading interserver configuration...\n");
+	ShowStatus("End reading login server configuration...\n");
 	return 0;
 }
 
 int do_init(int argc, char** argv)
 {
 	int input;
-	login_config_read( (argc > 1) ? argv[1] : INTER_CONF_NAME );
-	read_gm_account();
+
+	txtdb = account_db_txt();
+	sqldb = account_db_sql();
+
+	login_config_read( (argc > 1) ? argv[1] : LOGIN_CONF_NAME );
 
 	ShowInfo("\nWarning : Make sure you backup your databases before continuing!\n");
 	ShowInfo("\nDo you wish to convert your Login Database to SQL? (y/n) : ");
 	input = getchar();
+
 	if(input == 'y' || input == 'Y')
 		convert_login();
+
 	return 0;
 }
 
 void do_final(void)
 {
-	if( gm_account_db )
-	{
-		db_destroy(gm_account_db);
-		gm_account_db = NULL;
-	}
+	txtdb->destroy(txtdb);
+	sqldb->destroy(sqldb);	
 }

+ 0 - 0
src/zlib/zlib-1.2.3


+ 0 - 204
tools/cgi/addaccount.cgi

@@ -1,204 +0,0 @@
-#!/usr/bin/perl
-
-#=========================================================================
-# addaccount.cgi  ver.1.00
-#	ladminをラップした、アカウントを作成するCGI。
-#	ladmin ver.1.04での動作を確認。
-#
-# ** 設定方法 **
-#
-# - 下の$ladmin変数にladminへのパスを設定すること。
-# - UNIX系OSで使用する場合はladminと共に改行コードを変換すること、また
-#   ファイル先頭行をperlの正しいパスにすること。例> $ which perl
-# - サーバープログラムやブラウザによっては $cgiuri にこのファイルへの
-#   完全なURIをセットしなければならない場合もある。
-# - perlにパスが通っていない場合は $perl をperlへの正しいパスにすること。
-# - 他は普通のCGIと同じです。(実行権やcgi-binフォルダなど)
-#
-# ** その他 **
-#   addaccount.cgi をブラウザで開くとサンプルHTML(そのまま使えます)が
-#   開きます。また、このcgiはブラウザから送られるAccept-Languageが
-#   jaで始まっていればメッセージの一部を日本語に変換します。
-#   (IEならインターネットオプションの言語設定で一番上に日本語を置く)
-#	それ以外の場合は英語のまま出力します。
-#-------------------------------------------------------------------------
-
-my($ladmin)	= "../ladmin";			# ladminのパス(おそらく変更が必要)
-
-my($cgiuri)	= "./addaccount.cgi";	# このファイルのURI
-my($perl)	= "perl";				# perlのコマンド名
-
-
-
-#--------------------------- 設定ここまで --------------------------------
-
-
-
-
-
-
-use strict;
-use CGI;
-
-my($cgi)= new CGI;
-my(%langconv)=(
-	'Athena login-server administration tool.*' => '',
-	'logged on.*' => '',
-);
-
-# ----- 日本語環境なら変換テーブルをセット -----
-if($ENV{'HTTP_ACCEPT_LANGUAGE'}=~/^ja/){
-	my(%tmp)=(
-		'Account \[(.+)\] is successfully created.*'
-			=> 'アカウント "$1" を作成しました.',
-		'Account \[(.+)\] creation failed\. same account exists.*'
-			=> 'アカウント "$1" は既に存在します.',
-		'Illeagal charactor found in UserID.*'
-			=> 'IDの中に不正な文字があります.',
-		'Illeagal charactor found in Password.*'
-			=> 'Passwordの中に不正な文字があります.',
-		'input UserID 4-24 bytes.'
-			=> 'IDは半角4~24文字で入力してください.',
-		'input Password 4-24 bytes.'
-			=> 'Passwordは半角4~24文字で入力してください.',
-		'Illeagal gender.*'
-			=> '性別がおかしいです.',
-		'Cant connect to login server.*'
-			=> 'ログインサーバーに接続できません.',
-		'login error.*'
-			=> 'ログインサーバーへの管理者権限ログインに失敗しました',
-		"Can't execute ladmin.*"
-			=> 'ladminの実行に失敗しました',
-		'UserID "(.+)" is already used.*'
-			=> 'ID "$1" は既に使用されています.',
-		'You can use UserID \"(.+)\".*'
-			=> 'ID "$1" は使用可能です.',
-		
-		'account making'	=>'アカウント作成',
-		'\>UserID'			=>'>ID',
-		'\>Password'		=>'>パスワード',
-		'\>Gender'			=>'>性別',
-		'\>Male'			=>'>男性',
-		'\>Female'			=>'>女性',
-		'\"Make Account\"'	=>'"アカウント作成"',
-		'\"Check UserID\"'	=>'"IDのチェック"',
-	);
-	map { $langconv{$_}=$tmp{$_}; } keys (%tmp);
-}
-
-# ----- 追加 -----
-if( $cgi->param("addaccount") ){
-	my($userid)= $cgi->param("userid");
-	my($passwd)= $cgi->param("passwd");
-	my($gender)= lc(substr($cgi->param("gender"),0,1));
-	if(length($userid)<4 || length($userid)>24){
-		HttpError("input UserID 4-24 bytes.");
-	}
-	if(length($passwd)<4 || length($passwd)>24){
-		HttpError("input Password 4-24 bytes.");
-	}
-	if($userid=~/[^0-9A-Za-z\@\_\-\']/){
-		HttpError("Illeagal charactor found in UserID.");
-	}
-	if($passwd=~/[\x00-\x1f\x80-\xff\']/){
-		HttpError("Illeagal charactor found in Password.");
-	}
-	if($gender!~/[mf]/){
-		HttpError("Gender error.");
-	}
-	open PIPE,"$perl $ladmin --add $userid $gender $passwd |"
-		or HttpError("Can't execute ladmin.");
-	my(@msg)=<PIPE>;
-	close PIPE;
-	HttpMsg(@msg);
-}
-# ----- 存在チェック -----
-elsif( $cgi->param("check") ){
-	my($userid)= $cgi->param("userid");
-	if(length($userid)<4 || length($userid)>24){
-		HttpError("input UserID 4-24 bytes.");
-	}
-	if($userid=~/[^0-9A-Za-z\@\_\-\']/){
-		HttpError("Illeagal charactor found in UserID.");
-	}
-	open PIPE,"$perl $ladmin --search --regex \\b$userid\\b |"
-		or HttpError("Can't execute ladmin.");
-	my(@msg)=<PIPE>;
-	close PIPE;
-	if(scalar(@msg)==6 && (split /[\s\0]+/,substr($msg[4],11,24))[0] eq $userid){
-		HttpMsg("NG : UserID \"$userid\" is already used.");
-	}elsif(scalar(@msg)==5){
-		HttpMsg("OK : You can use UserID \"$userid\"");
-	}
-	HttpError("ladmin error ?\n---output---\n",@msg);
-}
-
-# ----- フォーム -----
-else{
-	print LangConv( <<"EOM" );
-Content-type: text/html\n
-<html>
- <head>
-  <title>Athena account making cgi</title>
- </head>
- <body>
-  <h1>Athena account making cgi</h1>
-  <form action="$cgiuri" method="post">
-   <table border=2>
-    <tr>
-     <th>UserID</th>
-     <td><input name="userid" size=24 maxlength=24></td>
-    </tr>
-    <tr>
-     <th>Password</th>
-     <td><input name="passwd" size=24 maxlength=24 type="password"></td>
-    </tr>
-    <tr>
-     <th>Gender</th>
-     <td>
-      <input type="radio" name="gender" value="male">Male
-      <input type="radio" name="gender" value="female">Female
-     </td>
-    </tr>
-    <tr>
-     <td colspan=2>
-      <input type="submit" name="addaccount" value="Make Account">
-      <input type="submit" name="check" value="Check UserID">
-     </td>
-    </tr>
-   </table>
-  </form>
- </body>
-</html>
-EOM
-	exit;
-}
-
-sub LangConv {
-	my(@lst)= @_;
-	my($a,$b,@out)=();
-	foreach $a(@lst){
-		foreach $b(keys %langconv){
-			$a=~s/$b/$langconv{$b}/g;
-			my($rep1)=$1;
-			$a=~s/\$1/$rep1/g;
-		}
-		push @out,$a;
-	}
-	return @out;
-}
-
-sub HttpMsg {
-	my($msg)=join("", LangConv(@_));
-	$msg=~s/\n/<br>\n/g;
-	print LangConv("Content-type: text/html\n\n"),$msg;
-	exit;
-}
-
-sub HttpError {
-	my($msg)=join("", LangConv(@_));
-	$msg=~s/\n/<br>\n/g;
-	print LangConv("Content-type: text/html\n\n"),$msg;
-	exit;
-}
-

+ 0 - 3793
tools/ladmin

@@ -1,3793 +0,0 @@
-#!/usr/bin/perl
-use POSIX;
-##########################################################################
-# EAthena login-server remote administration tool
-# New ladamin by [Yor]
-##########################################################################
-#-------------------------------INSTRUCTIONS------------------------------
-# Set the 4 variables below:
-#   IP of the login server.
-#   Port where the login-server listens incoming packets.
-#   Password of administration (same of config_athena.conf).
-#   Displayed language of the sofware (if not correct, english is used).
-# IMPORTANT:
-#   Be sure that you authorize remote administration in login-server
-#   (see login_athena.conf, 'admin_state' parameter)
-#-------------------------------------------------------------------------
-my($loginserverip) = "127.0.0.1";        # IP of login-server
-my($loginserverport) = 6900;             # Port of login-server
-my($loginserveradminpassword) = "admin"; # Administration password
-my($connecttimeout) = 10;                # Timeout of connection (in seconds)
-my($passenc) = 2;                        # Encoding type of the password
-my($defaultlanguage) = "E";              # Default language (F: Français/E: English)
-                                         # (if it's not 'F', default is English)
-
-#-------------------------------------------------------------------------
-#  LIST of COMMANDs that you can type at the prompt:
-#    To use these commands you can only type only the first letters.
-#    You must type a minimum of letters (you can not type 'a',
-#      because ladmin doesn't know if it's for 'aide' or for 'add')
-#    <Example> q <= quit, li <= list, pass <= passwd, etc.
-#
-#  Note: every time you must give a account_name, you can use "" or '' (spaces can be included)
-#
-#  aide/help/?
-#    Display the description of the commands
-#  aide/help/? [command]
-#    Display the description of the specified command
-#
-#  add <account_name> <sex> <password>
-#    Create an account with the default email (a@a.com).
-#    Concerning the sex, only the first letter is used (F or M).
-#    The e-mail is set to a@a.com (default e-mail). It's like to have no e-mail.
-#    When the password is omitted, the input is done without displaying of the pressed keys.
-#    <example> add testname Male testpass
-#
-#  ban/banish yyyy/mm/dd hh:mm:ss <account name>
-#    Changes the final date of a banishment of an account.
-#    Same command of banset, except that account_name is at end
-#
-#  banadd <account_name> <modifier>
-#    Adds or substracts time from the final date of a banishment of an account.
-#    Modifier is done as follows:
-#      Adjustment value (-1, 1, +1, etc...)
-#      Modified element:
-#        a or y: year
-#        m:  month
-#        j or d: day
-#        h:  hour
-#        mn: minute
-#        s:  second
-#    <example> banadd testname +1m-2mn1s-6y
-#              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-#  NOTE: If you modify the final date of a non-banished account,
-#        you fix the final date to (actual time +- adjustments)
-#
-#  banset <account_name> yyyy/mm/dd [hh:mm:ss]
-#    Changes the final date of a banishment of an account.
-#    Default time: 23:59:59
-#  banset <account_name> 0
-#    Set a non-banished account (0 = unbanished).
-#
-#  block <account name>
-#    Set state 5 (You have been blocked by the GM Team) to an account.
-#    Same command of state <account_name> 5.
-#
-#  check <account_name> <password>
-#    Check the validity of a password for an account
-#    NOTE: Server will never sends back a password.
-#          It's the only method you have to know if a password is correct.
-#          The other method is to have a ('physical') access to the accounts file.
-#
-#  create <account_name> <sex> <email> <password>
-#    Like the 'add' command, but with e-mail moreover.
-#    <example> create testname Male my@mail.com testpass
-#
-#  del <account name>
-#    Remove an account.
-#    This order requires confirmation. After confirmation, the account is deleted.
-#
-#  email <account_name> <email>
-#    Modify the e-mail of an account.
-#
-#  getcount
-#    Give the number of players online on all char-servers.
-#
-#  gm <account_name> [GM_level]
-#    Modify the GM level of an account.
-#    Default value remove GM level (GM level = 0).
-#    <example> gm testname 80
-#
-#  id <account name>
-#    Give the id of an account.
-#
-#  info <account_id>
-#    Display complete information of an account.
-#
-#  kami <message>
-#    Sends a broadcast message on all map-server (in yellow).
-#  kamib <message>
-#    Sends a broadcast message on all map-server (in blue).
-#
-#  language <language>
-#    Change the language of displaying.
-#
-#  list/ls [start_id [end_id]]
-#    Display a list of accounts.
-#    'start_id', 'end_id': indicate end and start identifiers.
-#    Research by name is not possible with this command.
-#    <example> list 10 9999999
-#
-#  listBan/lsBan [start_id [end_id]]
-#    Like list/ls, but only for accounts with state or banished
-#
-#  listGM/lsGM [start_id [end_id]]
-#    Like list/ls, but only for GM accounts
-#
-#  listOK/lsOK [start_id [end_id]]
-#    Like list/ls, but only for accounts without state and not banished
-#
-#  memo <account_name> <memo>
-#    Modify the memo of an account.
-#    'memo': it can have until 253 characters (with spaces or not).
-#
-#  name <account_id>
-#    Give the name of an account.
-#
-#  passwd <account_name> <new_password>
-#    Change the password of an account.
-#    When new password is omitted, the input is done without displaying of the pressed keys.
-#
-#  quit/end/exit
-#    End of the program of administration
-#
-#  reloadGM
-#    Reload GM configuration file
-#
-#  search <expression>
-#    Seek accounts.
-#    Displays the accounts whose names correspond.
-#  search -r/-e/--expr/--regex <expression>
-#    Seek accounts by regular expression.
-#    Displays the accounts whose names correspond.
-#
-#  sex <account_name> <sex>
-#    Modify the sex of an account.
-#    <example> sex testname Male
-#
-#  state <account_name> <new_state> <error_message_#7>
-#    Change the state of an account.
-#    'new_state': state is the state of the packet 0x006a + 1. The possibilities are:
-#                 0 = Account ok            6 = Your Game's EXE file is not the latest version
-#                 1 = Unregistered ID       7 = You are Prohibited to log in until %s
-#                 2 = Incorrect Password    8 = Server is jammed due to over populated
-#                 3 = This ID is expired    9 = No MSG
-#                 4 = Rejected from Server  100 = This ID has been totally erased
-#                 5 = You have been blocked by the GM Team
-#                 all other values are 'No MSG', then use state 9 please.
-#    'error_message_#7': message of the code error 6 = Your are Prohibited to log in until %s (packet 0x006a)
-#
-#  timeadd <account_name> <modifier>
-#    Adds or substracts time from the validity limit of an account.
-#    Modifier is done as follows:
-#      Adjustment value (-1, 1, +1, etc...)
-#      Modified element:
-#        a or y: year
-#        m:  month
-#        j or d: day
-#        h:  hour
-#        mn: minute
-#        s:  second
-#    <example> timeadd testname +1m-2mn1s-6y
-#              this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time.
-#  NOTE: You can not modify a unlimited validity limit.
-#        If you want modify it, you want probably create a limited validity limit.
-#        So, at first, you must set the validity limit to a date/time.
-#
-#  timeset <account_name> yyyy/mm/dd [hh:mm:ss]
-#    Changes the validity limit of an account.
-#    Default time: 23:59:59
-#  timeset <account_name> 0
-#    Gives an unlimited validity limit (0 = unlimited).
-#
-#  unban/unbanish <account name>
-#    Unban an account.
-#    Same command of banset 0.
-#
-#  unblock <account name>
-#    Set state 0 (Account ok) to an account.
-#    Same command of state <account_name> 0.
-#
-#  version
-#    Display the version of the login-server.
-#
-#  who <account name>
-#    Displays complete information of an account.
-#
-#-------------------------------------------------------------------------
-# Possibilities to execute ladmin in command line by usage of the software with a parameter:
-# ./ladmin --mode param1 ...
-#
-#  --makesymlink                                    -- Create the symbolic links for a use in shell
-#  --add <account_name> <sex> <password>            -- Create an account with the default email (or -a)
-#  --ban yyyy/mm/dd hh:mm:ss <account_name>         -- Change the final date of a banishment of an account (or -b)
-#  --banadd <account_name> <modifier>               -- Add or substract time from the final date of a banishment of an account (or - ba)
-#  --banset <account_name> yyyy/mm/dd [hh:mm:ss]    -- Change the final date of a banishment of an account (or -bs)
-#  --banset <account_name> 0                        -- Unbanish an account (or -bs)
-#  --block <account_name>                           -- Set state 5 to an account (or -bl)
-#  --check <account_name> <password>                -- Check the validity of a password for an account (or -check)
-#  --create <account_name> <sex> <email> <password> -- Create an account with email (or -c)
-#  --del <account_name>                             -- Remove an account (or -d)
-#  --email <account_name> <email>                   -- Modify an email of an account (or -e)
-#  --getcount                                       -- Give the number of players online on all char-servers (or -g)
-#  --gm <account_name> <GM_level>                   -- Change the GM level of an account (or -gm)
-#  --id <account_name>                              -- Give the id of an account (or -i)
-#  --info <account_id>                              -- Display complete information of an account (or -info)
-#  --kami <message>                                 -- Sends a broadcast message on all map-server (in yellow).
-#  --kamib <message>                                -- Sends a broadcast message on all map-server (in blue).
-#  --language <language>                            -- Change the language of displaying (-lang).
-#  --list [First_id [Last_id]]                      -- Display a list of accounts (or -l)
-#  --listBan [start_id [end_id]]                    -- Display a list of accounts with state or banished (or -lBan)
-#  --listGM [First_id [Last_id]]                    -- Display a list of GM accounts (or -lGM)
-#  --listOK [start_id [end_id]]                     -- Display a list of accounts without state and not banished (or -lOK)
-#  --memo <account_name> <memo>                     -- Modify the memo of an account (or -e)
-#  --name <account_id>                              -- Give the name of an account (or -n)
-#  --passwd <account_name> <new_password>           -- Change the password of an account (or -p)
-#  --reloadGM                                       -- Reload GM configuration file (or -r)
-#  --search <expression>                            -- Seek accounts (or -s)
-#  --search -e/-r/--expr/--regex <expression>       -- Seek accounts by REGEX (or -s)
-#  --sex <account_name> <sex>                       -- Change the sex of an account (or -sex)
-#  --state <account_name> <new_state> <error_message_#7> -- Change the state of an account (or -t)
-#  --timeadd <account_name> <modifier>              -- Add or substract time from the validity limit of an account (or - ta)
-#  --timeset <account_name> yyyy/mm/dd [hh:mm:ss]   -- Change the validify limit of an account (or -ts)
-#  --timeset <account_name> 0                       -- Give a unlimited validity limit (or -ts)
-#  --unban/unbanish <account_name>                  -- Unban an account (or -uba)
-#  --unblock <account_name>                         -- Set state 0 to an account (or -ubl)
-#  --version                                        -- Display the version of the login-server (or -v)
-#  --who <account_name>                             -- Display complete information of an account (or -w)
-#
-#  <example> ./ladmin --addaccount testname Male testpass
-#
-#-------------------------------------------------------------------------
-# Possibilities to execute ladmin with symbolic links in Shell
-# To create the symbolic links, execute ladmin with the '-- makesymlink' option.
-#
-#  addaccount <account_name> <sex> <password>            -- Create an account with the default email
-#  banaccount yyyy/mm/dd hh:mm:ss <account_name>         -- Change the final date of a banishment of an account
-#  banaddaccount <account_name> <modifier>               -- Add or substract time from the final date of a banishment of an account
-#  bansetaccount <account_name> yyyy/mm/dd [hh:mm:ss]    -- Change the final date of a banishment of an account
-#  bansetaccount <account_name> 0                        -- Unbanish an account
-#  blockaccount <account_name>                           -- Set state 5 (blocked by the GM Team) to an account
-#  checkaccount <account_name> <password>                -- Check the validity of a password for an account
-#  createaccount <account_name> <sex> <email> <password> -- Create an account with email
-#  delaccount <account_name>                             -- Remove an account
-#  emailaccount <account_name> <email>                   -- Modify an email of an account
-#  getcount                                              -- Give the number of players online on all char-servers
-#  gmaccount <account_name> <GM_level>                   -- Change the GM level of an account
-#  idaccount <account_name>                              -- Give the id of an account
-#  infoaccount <account_id>                              -- Display complete information of an account
-#  kami <message>                                        -- Sends a broadcast message on all map-server (in yellow).
-#  kamib <message>                                       -- Sends a broadcast message on all map-server (in blue).
-#  ladminlanguage <language>                             -- Change the language of displaying.
-#  listaccount [First_id [Last_id]]                      -- Display a list of accounts
-#  listBanaccount [start_id [end_id]]                    -- Display a list of accounts with state or banished
-#  listGMaccount [First_id [Last_id]]                    -- Display a list of GM accounts
-#  listOKaccount [start_id [end_id]]                     -- Display a list of accounts without state and not banished
-#  loginserverversion                                    -- Display the version of the login-server
-#  memoaccount <account_name> <memo>                     -- Modify the memo of an account
-#  nameaccount <account_id>                              -- Give the name of an account
-#  passwdaccount <account_name> <new_password>           -- Change the password of an account
-#  reloadGM                                              -- Reload GM configuration file
-#  searchaccount <expression>                            -- Seek accounts
-#  searchaccount -e/-r/--expr/--regex <expression>       -- Seek accounts by REGEX
-#  sexaccount <account_name> <sex>                       -- Change the sex of an account (or -sex)
-#  stateaccount <account_name> <new_state> <error_message_#7> -- Change the state of an account
-#  timeaddaccount <account_name> <modifier>              -- Add or substract time from the validity limit of an account
-#  timesetaccount <account_name> yyyy/mm/dd [hh:mm:ss]   -- Change the validify limit of an account
-#  timesetaccount <account_name> 0                       -- Give a unlimited validity limit
-#  unbanaccount <account_name>                           -- Unban an account
-#  unblockaccount <account_name>                         -- Set state 0 (Account ok) to an account
-#  whoaccount <account_name>                             -- Display complete information of an account
-#  <exemple> ./addaccount testname Male testpass
-#
-#-------------------------------------------------------------------------
-# About the encoding:
-#
-#   The Digest::MD5 module is necessary to use the encrypted password system.
-#   When the software cannot found the Digest::MD5 module,
-#     encoding is automatically disabled ($passenc=0), which allows
-#     to use this program in any cases.
-#
-#-------------------------------------------------------------------------
-# How to use ladmin with UNIX:
-#
-# You excecute ladmin as a standard command.
-#  <Example of preparation to have an access to ladmin>
-#    $ mv ladmin ladmin_org
-#    $ nkf -eLu ladmin_org > ladmin
-#    $ chmod 700 ladmin
-#  <Example to start directly ladmin>
-#    $ perl ladmin
-#
-##########################################################################
-
-
-use strict;
-use IO::Socket;
-use Term::ReadLine;
-eval { use POSIX qw(:termios_h); };
-eval { use Digest::MD5 qw(md5); } if $passenc;
-$passenc = 0 if($@);
-
-my($ver) = "1.00";
-
-# Start of termios
-my($termios, $orgterml, $termlecho, $termlnoecho) = ();
-eval{
-	$termios = POSIX::Termios->new();
-	$termios->getattr(fileno(STDIN));
-	$orgterml = $termios->getlflag();
-	$termlecho = ECHO | ECHOK | ICANON;
-	$termlnoecho = $orgterml & ~$termlecho;
-};
-
-# Modification of termios for the displaying of passwords (no displays for pressed keys)
-sub cbreak() {
-	if ($termios) {
-		$termios->setlflag($termlnoecho);
-		$termios->setcc(VTIME, 1);
-		$termios->setattr(fileno(STDIN), TCSANOW);
-	}
-}
-# Modification of termios to return at the normal displaying (after input of the passwords)
-sub cooked() {
-	if ($termios) {
-		$termios->setlflag($orgterml);
-		$termios->setcc(VTIME,0);
-		$termios->setattr(fileno(STDIN),TCSANOW);
-	}
-}
-END{ cooked() }
-
-if ($defaultlanguage eq "F") {
-	print "Outil d'administration à distance de eAthena V.$ver\n";
-} else {
-	print "EAthena login-server administration tool V.$ver\n";
-}
-
-# Creation of the symbolic links for call of the program in line command of the shell
-if ($ARGV[0] eq "--makesymlink") {
-	symlink $0, "loginserverversion";
-	symlink $0, "addaccount";
-	symlink $0, "banaccount";
-	symlink $0, "banaddaccount";
-	symlink $0, "bansetaccount";
-	symlink $0, "blockaccount";
-	symlink $0, "checkaccount";
-	symlink $0, "createaccount";
-	symlink $0, "delaccount";
-	symlink $0, "emailaccount";
-	symlink $0, "getcount";
-	symlink $0, "gmaccount";
-	symlink $0, "idaccount";
-	symlink $0, "infoaccount";
-	symlink $0, "kami";
-	symlink $0, "kamib";
-	symlink $0, "ladminlanguage";
-	symlink $0, "listaccount";
-	symlink $0, "listBanaccount";
-	symlink $0, "listGMaccount";
-	symlink $0, "listOKaccount";
-	symlink $0, "memoaccount";
-	symlink $0, "nameaccount";
-	symlink $0, "passwdaccount";
-	symlink $0, "reloadGM";
-	symlink $0, "searchaccount";
-	symlink $0, "sexaccount";
-	symlink $0, "stateaccount";
-	symlink $0, "timeaddaccount";
-	symlink $0, "timesetaccount";
-	symlink $0, "unbanaccount";
-	symlink $0, "unblockaccount";
-	symlink $0, "whoaccount";
-	if ($defaultlanguage eq "F") {
-		print "Liens symbliques créés.\n";
-	} else {
-		print "Symbolic links created.\n";
-	}
-	exit(0);
-}
-
-# Connection to the login-server
-my($so,$er) = ();
-eval{
-	$so = IO::Socket::INET->new(
-		PeerAddr=> $loginserverip,
-		PeerPort=> $loginserverport,
-#		Proto   => "tcp",
-		Timeout => $connecttimeout) or $er = 1;
-};
-if ($er || $@) {
-	if ($defaultlanguage eq "F") {
-		print "\nImpossible de se connecter au serveur de login [${loginserverip}:$loginserverport] !\n";
-	} else {
-		print "\nImpossible to have a connection with the login-server [${loginserverip}:$loginserverport] !\n";
-	}
-	print "$!\n";	# Displaying of the error
-	exit(2);
-}
-
-# Sending the administration password
-if ($passenc == 0) {
-	print $so pack("v2a24",0x7918,0,$loginserveradminpassword);
-	$so->flush();
-} else {
-	print $so pack("v",0x791a);
-	$so->flush();
-	my($buf) = readso(4);
-	if (unpack("v",$buf) != 0x01dc) {
-		if ($defaultlanguage eq "F") {
-			print "Erreur au login (échec de la création de la clef md5).\n";
-		} else {
-			print "Error at login (failure of the md5 key creation).\n";
-		}
-	}
-	$buf = readso(unpack("x2v",$buf)-4);
-	my($md5bin) = md5(($passenc == 1) ? $buf.$loginserveradminpassword : $loginserveradminpassword.$buf);
-	print $so pack("v2a16",0x7918,$passenc,$md5bin);
-	$so->flush();
-}
-
-# Waiting of the server reply
-my($buf) = readso(3);
-
-if (unpack("v",$buf) != 0x7919 || unpack("x2c",$buf) != 0) {
-	if ($defaultlanguage eq "F") {
-		print "Erreur de login:\n";
-		print " - mot de passe incorrect,\n";
-		print " - système d'administration non activé, ou\n";
-		print " - IP non autorisée.\n";
-	} else {
-		print "Error at login:\n";
-		print " - incorrect password,\n";
-		print " - administration system not activated, or\n";
-		print " - unauthorised IP.\n";
-	}
-	quit();
-	exit(4);
-}
-
-if ($defaultlanguage eq "F") {
-	print "Connexion établie.\n";
-} else {
-	print "Established connection.\n";
-}
-
-#-------------------------------------------------------------------------
-# Here are checked the command lines with arguments and symbolic links (no prompt)
-
-if ($0 =~ /addaccount$/ ||
-    (($ARGV[0] eq "-a" || $ARGV[0] eq "--add") && ((shift @ARGV), 1))) {
-	my($r) = addaccount($ARGV[0], $ARGV[1], $ARGV[2]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /banaccount$/ || $0 =~ /banishaccount$/ ||
-         (($ARGV[0] eq "-b" || $ARGV[0] eq "--ban" || $ARGV[0] eq "--banish") && ((shift @ARGV), 1))) {
-	my($r) = bansetaccount($ARGV[1], $ARGV[2], $ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /banaddaccount$/ ||
-         (($ARGV[0] eq "-ba" || $ARGV[0] eq "--banadd") && ((shift @ARGV), 1))) {
-	my($r) = banaddaccount($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /bansetaccount$/ ||
-         (($ARGV[0] eq "-bs" || $ARGV[0] eq "--banset") && ((shift @ARGV), 1))) {
-	my($r) = bansetaccount($ARGV[0], $ARGV[1], $ARGV[2]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /blockaccount$/ ||
-         (($ARGV[0] eq "-bl" || $ARGV[0] eq "--block") && ((shift @ARGV), 1))) {
-	my($r) = changestate($ARGV[0], 5, "");
-	quit();
-	exit($r);
-} elsif ($0 =~ /checkaccount$/ ||
-         (($ARGV[0] eq "-check" || $ARGV[0] eq "--check") && ((shift @ARGV), 1))) {
-	my($r) = checkaccount($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /createaccount$/ ||
-         (($ARGV[0] eq "-c" || $ARGV[0] eq "--create") && ((shift @ARGV), 1))) {
-	my($r) = createaccount($ARGV[0], $ARGV[1], $ARGV[2], $ARGV[3]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /delaccount$/ ||
-         (($ARGV[0] eq "-d" || $ARGV[0] eq "--del") && ((shift @ARGV), 1))) {
-	my($r) = delaccount($ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /emailaccount$/ ||
-         (($ARGV[0] eq "-e" || $ARGV[0] eq "--email") && ((shift @ARGV), 1))) {
-	my($r) = changeemail($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /getcount$/ ||
-         (($ARGV[0] eq "-g" || $ARGV[0] eq "--getcount") && ((shift @ARGV), 1))) {
-	my($r) = getlogincount();
-	quit();
-	exit($r);
-} elsif ($0 =~ /gmaccount$/ ||
-         (($ARGV[0] eq "-gm" || $ARGV[0] eq "--gm") && ((shift @ARGV), 1))) {
-	my($r) = changegmlevel($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /id$/ ||
-         (($ARGV[0] eq "-i" || $ARGV[0] eq "--id") && ((shift @ARGV), 1))) {
-	my($r) = idaccount($ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /infoaccount$/ ||
-         (($ARGV[0] eq "-info" || $ARGV[0] eq "--info") && ((shift @ARGV), 1))) {
-	my($r) = infoaccount($ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /kami$/ ||
-         (($ARGV[0] eq "-kami" || $ARGV[0] eq "--kami") && ((shift @ARGV), 1))) {
-	my($r) = sendbroadcast(0, $ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /kamib$/ ||
-         (($ARGV[0] eq "-kamib" || $ARGV[0] eq "--kamib") && ((shift @ARGV), 1))) {
-	my($r) = sendbroadcast(0x10, $ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /ladminlanguage$/ ||
-         (($ARGV[0] eq "-lang" || $ARGV[0] eq "--language") && ((shift @ARGV), 1))) {
-	my($r) = changelanguage($ARGV[0]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /listaccount$/ ||
-         (($ARGV[0] eq "-l" || $ARGV[0] eq "--list") && ((shift @ARGV), 1))) {
-	my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 0); # 0: to list all
-	quit();
-	exit($r);
-} elsif ($0 =~ /listBanaccount$/ ||
-         (($ARGV[0] eq "-lBan" || $ARGV[0] eq "--listBan") && ((shift @ARGV), 1))) {
-	my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 3); # 3: to list only accounts with state or banished
-	quit();
-	exit($r);
-} elsif ($0 =~ /listGMaccount$/ ||
-         (($ARGV[0] eq "-lGM" || $ARGV[0] eq "--listGM") && ((shift @ARGV), 1))) {
-	my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 1); # 1: to list only GM
-	quit();
-	exit($r);
-} elsif ($0 =~ /listOKaccount$/ ||
-         (($ARGV[0] eq "-lOK" || $ARGV[0] eq "--listOK") && ((shift @ARGV), 1))) {
-	my($r) = listaccount(int($ARGV[0]), int($ARGV[1]), 4); # 4: to list only accounts without state and not banished
-	quit();
-	exit($r);
-} elsif ($0 =~ /loginserverversion$/ ||
-         (($ARGV[0] eq "-v" || $ARGV[0] eq "--version") && ((shift @ARGV), 1))) {
-	my($r) = checkloginversion();
-	quit();
-	exit($r);
-} elsif ($0 =~ /memoaccount$/ ||
-         (($ARGV[0] eq "-m" || $ARGV[0] eq "--memo") && ((shift @ARGV), 1))) {
-	my($r) = changememo($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /nameaccount$/ ||
-         (($ARGV[0] eq "-n" || $ARGV[0] eq "--name") && ((shift @ARGV), 1))) {
-	my($r) = nameaccount(int($ARGV[0]));
-	quit();
-	exit($r);
-} elsif ($0 =~ /passwdaccount$/ ||
-         (($ARGV[0] eq "-p" || $ARGV[0] eq "--passwd") && ((shift @ARGV), 1))) {
-	my($r) = changepasswd($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /reloadGM$/ ||
-         (($ARGV[0] eq "-r" || $ARGV[0] eq "--reloadGM") && ((shift @ARGV), 1))) {
-	my($r) = reloadGM();
-	quit();
-	exit($r);
-} elsif ($0 =~ /searchaccount$/ ||
-         (($ARGV[0] eq "-s" || $ARGV[0] eq "--search") && ((shift @ARGV), 1))) {
-	my($r) = searchaccount($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /sexaccount$/ ||
-         (($ARGV[0] eq "-sex" || $ARGV[0] eq "--sex") && ((shift @ARGV), 1))) {
-	my($r) = changesex($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /stateaccount$/ ||
-         (($ARGV[0] eq "-t" || $ARGV[0] eq "--state") && ((shift @ARGV), 1))) {
-	my($r) = changestate($ARGV[0], $ARGV[1], $ARGV[2]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /timeaddaccount$/ ||
-         (($ARGV[0] eq "-ta" || $ARGV[0] eq "--timeadd") && ((shift @ARGV), 1))) {
-	my($r) = timeaddaccount($ARGV[0], $ARGV[1]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /timesetaccount$/ ||
-         (($ARGV[0] eq "-ts" || $ARGV[0] eq "--timeset") && ((shift @ARGV), 1))) {
-	my($r) = timesetaccount($ARGV[0], $ARGV[1], $ARGV[2]);
-	quit();
-	exit($r);
-} elsif ($0 =~ /unbanaccount$/ || $0 =~ /unbanishaccount$/ ||
-         (($ARGV[0] eq "-uba" || $ARGV[0] eq "--unban" || $ARGV[0] eq "--unbanish") && ((shift @ARGV), 1))) {
-	my($r) = bansetaccount($ARGV[0], 0, "");
-	quit();
-	exit($r);
-} elsif ($0 =~ /unblockaccount$/ ||
-         (($ARGV[0] eq "-ubl" || $ARGV[0] eq "--unblock") && ((shift @ARGV), 1))) {
-	my($r) = changestate($ARGV[0], 0, "");
-	quit();
-	exit($r);
-} elsif ($0 =~ /whoaccount$/ ||
-         (($ARGV[0] eq "-w" || $ARGV[0] eq "--who") && ((shift @ARGV), 1))) {
-	my($r) = whoaccount($ARGV[0]);
-	quit();
-	exit($r);
-}
-
-#-------------------------------------------------------------------------
-if ($defaultlanguage eq "F") {
-	print "Lecture de la version du serveur de login...\n";
-} else {
-	print "Reading of the version of the login-server...\n";
-}
-checkloginversion();
-
-# Set the prompt line
-my($term) = new Term::ReadLine "ladmin";
-
-# Here begin the infinite loop to read prompts
-while(1) {
-	# Displaying of the prompt
-	print "\n";
-	if ($defaultlanguage eq "F") {
-		printf "\033[32mPour afficher les commandes, tapez 'Entrée'.\033[0m\n";
-	} else {
-		printf "\033[32mTo list the commands, type 'enter'.\033[0m\n";
-	}
-	my($cmd) = $term->readline("ladmin> ");
-	# split and recovery of the input
-	chomp $cmd; # remove cariage return
-	$cmd =~ s/\x1b\[\d*\w//g; # remove (esc)[(number)(1alpha) = screen control sequence
-	$cmd =~ s/[\x00-\x1f]//g; # remove control char
-	my($command, $parameters) = split /\s+/,$cmd,2; # extract command and parameters
-	$command = lc($command); # command in lowercase
-	my(@paramlist) = split /\s+/,$parameters; # get list of parameters
-
-	if ($command eq "?" || $command eq "") {
-		$command = "aide" if ($defaultlanguage eq "F");
-		$command = "help" if ($defaultlanguage ne "F");
-	}
-
-	# Analyse of the command
-	eval {
-# help
-		if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			displayhelp("aide", $paramlist[0]);
-		} elsif ("help" =~ /^\Q$command/) {
-			displayhelp("help", $paramlist[0]);
-
-# general commands
-		} elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(.*)/)) {
-				addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				addaccount($paramlist[0], $paramlist[1], ""); # <account_name> <sex> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(.*)/)) {
-				addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				addaccount($paramlist[0], $paramlist[1], ""); # <account_name> <sex> <password>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				addaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> <sex> <password>
-			}
-
-		} elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) {
-			if (@paramlist = ($parameters =~ m/^(\S+)\s+(\S+)\s+"(.*)"/)) { # yyyy/mm/dd hh:mm:ss <account_name>
-				bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^(\S+)\s+(\S+)\s+'(.*)'/)) { # yyyy/mm/dd hh:mm:ss <account_name>
-				bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} else {
-				@paramlist = split /\s+/,$parameters,3; # yyyy/mm/dd hh:mm:ss <account_name>
-				bansetaccount($paramlist[2], $paramlist[0], $paramlist[1]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			}
-
-		} elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				banaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			}
-
-		} elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) {
-				bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				bansetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) {
-				bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				bansetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				bansetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			}
-
-		} elsif ("block" =~ /^\Q$command/ && length($command) >= 2) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				changestate($paramlist[0], 5, ""); # <account_name> <new_state> <error_message_#7>
-			}
-
-		} elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) {
-				checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				checkaccount($paramlist[0], ""); # <account_name> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) {
-				checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				checkaccount($paramlist[0], ""); # <account_name> <password>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				checkaccount($paramlist[0], $paramlist[1]); # <account_name> <password>
-			}
-
-		} elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)\s+(.*)/)) {
-				createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) {
-				createaccount($paramlist[0], $paramlist[1], $paramlist[2], ""); # <account_name> <sex> <email> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)\s+(.*)/)) {
-				createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) {
-				createaccount($paramlist[0], $paramlist[1], $paramlist[2], ""); # <account_name> <sex> <email> <password>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				createaccount($paramlist[0], $paramlist[1], $paramlist[2], $paramlist[3]); # <account_name> <sex> <email> <password>
-			}
-
-		} elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				delaccount($paramlist[0]); # <account_name>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				delaccount($paramlist[0]); # <account_name>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				delaccount($paramlist[0]); # <account_name>
-			}
-
-		} elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				changeemail($paramlist[0], $paramlist[1]); # <account_name> <email>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				changeemail($paramlist[0], $paramlist[1]); # <account_name> <email>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				changeemail($paramlist[0], $paramlist[1]); # <account_name> <email>
-			}
-
-		} elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			getlogincount();
-
-		} elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				changegmlevel($paramlist[0], 0); # <account_name> <GM_level>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				changegmlevel($paramlist[0], 0); # <account_name> <GM_level>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				changegmlevel($paramlist[0], int($paramlist[1])); # <account_name> <GM_level>
-			}
-
-		} elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				idaccount($paramlist[0]); # <account_name>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				idaccount($paramlist[0]); # <account_name>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				idaccount($paramlist[0]); # <account_name>
-			}
-
-		} elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			infoaccount(int($paramlist[0])); # <account_id>
-
-		} elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'?
-			@paramlist = split /\s+/,$parameters,1;
-			sendbroadcast(0, $paramlist[0]); # <type> <message>
-
-		} elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'?
-			@paramlist = split /\s+/,$parameters,1;
-			sendbroadcast(0x10, $paramlist[0]); # <type> <message>
-
-		} elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			changelanguage($paramlist[0]); # <language>
-
-		} elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			listaccount(int($paramlist[0]), int($paramlist[1]), 0); # [start_id [end_id]] 0: to list all
-
-		} elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'?
-			listaccount(int($paramlist[0]), int($paramlist[1]), 3); # [start_id [end_id]] 3: to list only accounts with state or banished
-
-		} elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'?
-			listaccount(int($paramlist[0]), int($paramlist[1]), 1); # [start_id [end_id]] 1: to list only GM
-
-		} elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'?
-			listaccount(int($paramlist[0]), int($paramlist[1]), 4); # [start_id [end_id]] 4: to list only accounts without state and not banished
-
-		} elsif ("memo" =~ /^\Q$command/) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) {
-				changememo($paramlist[0], $paramlist[1]); # <account_name> <memo>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) {
-				changememo($paramlist[0], $paramlist[1]); # <account_name> <memo>
-			} else {
-				@paramlist = split /\s+/,$parameters,2;
-				changememo($paramlist[0], $paramlist[1]); # <account_name> <memo>
-			}
-
-		} elsif ("name" =~ /^\Q$command/) {
-			nameaccount(int($paramlist[0])); # <account_id>
-
-		} elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(.*)/)) {
-				changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				changepasswd($paramlist[0], ""); # <account_name> <new_password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(.*)/)) {
-				changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				changepasswd($paramlist[0], ""); # <account_name> <new_password>
-			} else {
-				@paramlist = split /\s+/,$parameters,2;
-				changepasswd($paramlist[0], $paramlist[1]); # <account_name> <new_password>
-			}
-
-		} elsif ("reloadgm" =~ /^\Q$command/) {
-			reloadGM();
-
-		} elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			if (@paramlist = ($parameters =~ m/^(-{1,2}[re]\S*)\s+(.*)/)) {
-				searchaccount($paramlist[0], $paramlist[1]); # -r/-e/--expr/--regex <expression> | <expression>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				searchaccount($paramlist[0], ""); # -r/-e/--expr/--regex <expression> | <expression>
-			}
-
-		} elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				changesex($paramlist[0], $paramlist[1]); # <account_name> <sex>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				changesex($paramlist[0], $paramlist[1]); # <account_name> <sex>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				changesex($paramlist[0], $paramlist[1]); # <account_name> <sex>
-			}
-
-		} elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\d+)\s+(.*)/)) {
-				changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7>
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\d+)/)) {
-				changestate($paramlist[0], int($paramlist[1]), ""); # <account_name> <new_state> <error_message_#7>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\d+)\s+(.*)/)) {
-				changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\d+)/)) {
-				changestate($paramlist[0], int($paramlist[1]), ""); # <account_name> <new_state> <error_message_#7>
-			} else {
-				@paramlist = split /\s+/,$parameters,3;
-				changestate($paramlist[0], int($paramlist[1]), $paramlist[2]); # <account_name> <new_state> <error_message_#7>
-			}
-
-		} elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				timeaddaccount($paramlist[0], $paramlist[1]); # <account_name> <modifier>
-			}
-
-		} elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			if (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)\s+(\S+)/)) {
-				timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^"(.*)"\s+(\S+)/)) {
-				timesetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)\s+(\S+)/)) {
-				timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'\s+(\S+)/)) {
-				timesetaccount($paramlist[0], $paramlist[1], "23:59:59"); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} else {
-				@paramlist = split /\s+/,$parameters;
-				timesetaccount($paramlist[0], $paramlist[1], $paramlist[2]); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			}
-
-		} elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				bansetaccount($paramlist[0], 0, ""); # <account_name> yyyy/mm/dd [hh:mm:ss]
-			}
-
-		} elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				changestate($paramlist[0], 0, ""); # <account_name> <new_state> <error_message_#7>
-			}
-
-		} elsif ("version" =~ /^\Q$command/) {
-			checkloginversion();
-
-		} elsif ("who" =~ /^\Q$command/) {
-			if (@paramlist = ($parameters =~ m/^"(.*)"/)) {
-				whoaccount($paramlist[0]); # <account_name>
-			} elsif (@paramlist = ($parameters =~ m/^'(.*)'/)) {
-				whoaccount($paramlist[0]); # <account_name>
-			} else {
-				@paramlist = split /\s+/,$parameters,1;
-				whoaccount($paramlist[0]); # <account_name>
-			}
-
-# quit
-		} elsif ("quit" =~ /^\Q$command/ ||
-		         (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'?
-			last;
-
-# unknown command
-		} elsif ($command) {
-			if ($defaultlanguage eq "F") {
-				print "Commande inconnue [".$command."]\n";
-			} else {
-				print "Unknown command [".$command."]\n";
-			}
-		}
-#		$term->addhistory($cmd) if $command;
-	};
-	if ($@) {
-		if ($defaultlanguage eq "F") {
-			print "Erreur [".$command."]\n$@";
-		} else {
-			print "Error [".$command."]\n$@";
-		}
-	}
-};
-
-# End of the software
-quit();
-
-if ($defaultlanguage eq "F") {
-	print "Au revoir.\n";
-} else {
-	print "Bye.\n";
-}
-exit(0);
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Displaying of the version of the login-server
-sub checkloginversion() {
-	print $so pack("v",30000); # 0x7530
-	$so->flush();
-	$buf = readso(10);
-	# Analyse du Packet
-	my($ret, $maver, $miver, $rev, $dev, $mod, $type, $mdver) = unpack("vc6v", $buf);
-	if ($ret != 30001) { #0x7531
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		exit(6);
-	}
-
-	print "  Login-Server [$loginserverip:$loginserverport]\n";
-	printf "  eAthena version %s-%d.%d", ("stable", "dev")[$dev], $maver, $miver;
-	printf " revision %d", $rev if $rev;
-	printf "%s%d.\n", ("", "-mod")[$mod], $mdver;
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Displaying of the help
-sub displayhelp() {
-	my($help, $receivedcommand) = @_;
-
-	my($command) = lc($receivedcommand); # command in lowercase
-
-	if ($command eq "") {
-		$command = "not a command"; # any value that is not a command
-	}
-
-	if ($command eq "?") {
-		$command = "aide" if ($defaultlanguage eq "F");
-		$command = "help" if ($defaultlanguage ne "F");
-	}
-
-	if ($help eq "aide") {
-		if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			printf "aide/help/?\n";
-			printf "  Affiche la description des commandes\n";
-			printf "aide/help/? [commande]\n";
-			printf "  Affiche la description de la commande specifiée\n";
-		} elsif ("help" =~ /^\Q$command/) {
-			printf "aide/help/?\n";
-			printf "  Display the description of the commands\n";
-			printf "aide/help/? [command]\n";
-			printf "  Display the description of the specified command\n";
-		} elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			printf "add <nomcompte> <sexe> <motdepasse>\n";
-			printf "  Crée un compte avec l'email par défaut (a\@a.com).\n";
-			printf "  Concernant le sexe, seule la première lettre compte (F ou M).\n";
-			printf "  L'e-mail est a\@a.com (e-mail par défaut). C'est comme n'avoir aucun e-mail.\n";
-			printf "  Lorsque motdepasse est omis, la saisie se fait sans que la frappe se voit.\n";
-			printf "  <exemple> add testname Male testpass\n";
-		} elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) {
-			printf "ban/banish aaaa/mm/jj hh:mm:ss <nomcompte>\n";
-			printf "  Change la date de fin de bannissement d'un compte.\n";
-			printf "  La différence avec banset est la position du nom du compte.\n";
-		} elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			printf "banadd <nomcompte> <Modificateur>\n";
-			printf "  Ajoute ou soustrait du temps à la date de banissement d'un compte.\n";
-			printf "  Les modificateurs sont construits comme suit:\n";
-			printf "    Valeur d'ajustement (-1, 1, +1, etc...)\n";
-			printf "    Elément modifié:\n";
-			printf "      a ou y: année\n";
-			printf "      m:      mois\n";
-			printf "      j ou d: jour\n";
-			printf "      h:      heure\n";
-			printf "      mn:     minute\n";
-			printf "      s:      seconde\n";
-			printf "  <exemple> banadd testname +1m-2mn1s-6a\n";
-			printf "            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n";
-			printf "            et 6 ans dans le même temps.\n";
-			printf "NOTE: Si vous modifez la date de banissement d'un compte non bani,\n";
-			printf "      vous indiquez comme date (le moment actuel +- les ajustements)\n";
-		} elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			printf "banset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n";
-			printf "  Change la date de fin de bannissement d'un compte.\n";
-			printf "  Heure par défaut: 23:59:59\n";
-			printf "banset <nomcompte> 0\n";
-			printf "  Débanni un compte (0 = de-banni).\n";
-		} elsif ("block" =~ /^\Q$command/ && length($command) >= 2) {
-			printf "block <nom compte>\n";
-			printf "  Place le status d'un compte à 5 (You have been blocked by the GM Team).\n";
-			printf "  La commande est l'équivalent de state <nom_compte> 5.\n";
-		} elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			printf "check <nomcompte> <motdepasse>\n";
-			printf "  Vérifie la validité d'un mot de passe pour un compte\n";
-			printf "  NOTE: Le serveur n'enverra jamais un mot de passe.\n";
-			printf "        C'est la seule méthode que vous possédez pour savoir\n";
-			printf "        si un mot de passe est le bon. L'autre méthode est\n";
-			printf "        d'avoir un accès ('physique') au fichier des comptes.\n";
-		} elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			printf "create <nomcompte> <sexe> <email> <motdepasse>\n";
-			printf "  Comme la commande add, mais avec l'e-mail en plus.\n";
-			printf "  <exemple> create testname Male mon\@mail.com testpass\n";
-		} elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) {
-			printf "del <nomcompte>\n";
-			printf "  Supprime un compte.\n";
-			printf "  La commande demande confirmation. Après confirmation, le compte est détruit.\n";
-		} elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'?
-			printf "email <nomcompte> <email>\n";
-			printf "  Modifie l'e-mail d'un compte.\n";
-		} elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			printf "getcount\n";
-			printf "  Donne le nombre de joueurs en ligne par serveur de char.\n";
-		} elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			printf "gm <nomcompte> [Niveau_GM]\n";
-			printf "  Modifie le niveau de GM d'un compte.\n";
-			printf "  Valeur par défaut: 0 (suppression du niveau de GM).\n";
-			printf "  <exemple> gm nomtest 80\n";
-		} elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			printf "id <nomcompte>\n";
-			printf "  Donne l'id d'un compte.\n";
-		} elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			printf "info <idcompte>\n";
-			printf "  Affiche les informations sur un compte.\n";
-		} elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'?
-			printf "kami <message>\n";
-			printf "  Envoi un message général sur tous les serveurs de map (en jaune).\n";
-		} elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'?
-			printf "kamib <message>\n";
-			printf "  Envoi un message général sur tous les serveurs de map (en bleu).\n";
-		} elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			printf("language <langue>\n");
-			printf("  Change la langue d'affichage.\n");
-			printf("  Langues possibles: 'Français' ou 'English'.\n");
-		} elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			printf "list/ls [Premier_id [Dernier_id]]\n";
-			printf "  Affiche une liste de comptes.\n";
-			printf "  'Premier_id', 'Dernier_id': indique les identifiants de départ et de fin.\n";
-			printf "  La recherche par nom n'est pas possible avec cette commande.\n";
-			printf "  <example> list 10 9999999\n";
-		} elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listBan/lsBan [Premier_id [Dernier_id]]\n";
-			printf "  Comme list/ls, mais seulement pour les comptes GM avec un statut ou bannis.\n";
-		} elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listGM/lsGM [Premier_id [Dernier_id]]\n";
-			printf "  Comme list/ls, mais seulement pour les comptes GM.\n";
-		} elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listOK/lsOK [Premier_id [Dernier_id]]\n";
-			printf "  Comme list/ls, mais seulement pour les comptes sans statut et non bannis.\n";
-		} elsif ("memo" =~ /^\Q$command/) {
-			printf "memo <nomcompte> <memo>\n";
-			printf "  Modifie le mémo d'un compte.\n";
-			printf "  'memo': Il peut avoir jusqu'à 253 caractères (avec des espaces ou non).\n";
-		} elsif ("name" =~ /^\Q$command/) {
-			printf "name <idcompte>\n";
-			printf "  Donne le nom d'un compte.\n";
-		} elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) {
-			printf "passwd <nomcompte> <nouveaumotdepasse>\n";
-			printf "  Change le mot de passe d'un compte.\n";
-			printf "  Lorsque nouveaumotdepasse est omis,\n";
-			printf "  la saisie se fait sans que la frappe ne se voit.\n";
-		} elsif ("reloadgm" =~ /^\Q$command/) {
-			printf "reloadGM\n";
-			printf "  Reload GM configuration file\n";
-		} elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			printf "search <expression>\n";
-			printf "  Cherche des comptes.\n";
-			printf "  Affiche les comptes dont les noms correspondent.\n";
-			printf "search -r/-e/--expr/--regex <expression>\n";
-			printf "  Cherche des comptes par expression regulière.\n";
-			printf "  Affiche les comptes dont les noms correspondent.\n";
-		} elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			printf "sex <nomcompte> <sexe>\n";
-			printf "  Modifie le sexe d'un compte.\n";
-			printf "  <exemple> sex testname Male\n";
-		} elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'?
-			printf "state <nomcompte> <nouveaustatut> <message_erreur_7>\n";
-			printf "  Change le statut d'un compte.\n";
-			printf "  'nouveaustatut': Le statut est le même que celui du packet 0x006a + 1.\n";
-			printf "               les possibilités sont:\n";
-			printf "               0 = Compte ok\n";
-			printf "               1 = Unregistered ID\n";
-			printf "               2 = Incorrect Password\n";
-			printf "               3 = This ID is expired\n";
-			printf "               4 = Rejected from Server\n";
-			printf "               5 = You have been blocked by the GM Team\n";
-			printf "               6 = Your Game's EXE file is not the latest version\n";
-			printf "               7 = You are Prohibited to log in until...\n";
-			printf "               8 = Server is jammed due to over populated\n";
-			printf "               9 = No MSG\n";
-			printf "               100 = This ID has been totally erased\n";
-			printf "               all other values are 'No MSG', then use state 9 please.\n";
-			printf "  'message_erreur_7': message du code erreur 6 =\n";
-			printf "                      = Your are Prohibited to log in until... (packet 0x006a)\n";
-		} elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			printf "timeadd <nomcompte> <modificateur>\n";
-			printf "  Ajoute/soustrait du temps à la limite de validité d'un compte.\n";
-			printf "  Le modificateur est composé comme suit:\n";
-			printf "    Valeur modificatrice (-1, 1, +1, etc...)\n";
-			printf "    Elément modifié:\n";
-			printf "      a ou y: année\n";
-			printf "      m:      mois\n";
-			printf "      j ou d: jour\n";
-			printf "      h:      heure\n";
-			printf "      mn:     minute\n";
-			printf "      s:      seconde\n";
-			printf "  <exemple> timeadd testname +1m-2mn1s-6a\n";
-			printf "            Cette exemple ajoute 1 mois et une seconde, et soustrait 2 minutes\n";
-			printf "            et 6 ans dans le même temps.\n";
-			printf "NOTE: Vous ne pouvez pas modifier une limite de validité illimitée. Si vous\n";
-			printf "      désirez le faire, c'est que vous voulez probablement créer un limite de\n";
-			printf "      validité limitée. Donc, en premier, fixé une limite de valitidé.\n";
-		} elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			printf "timeset <nomcompte> aaaa/mm/jj [hh:mm:ss]\n";
-			printf "  Change la limite de validité d'un compte.\n";
-			printf "  Heure par défaut: 23:59:59\n";
-			printf "timeset <nomcompte> 0\n";
-			printf "  Donne une limite de validité illimitée (0 = illimitée).\n";
-		} elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) {
-			printf "unban/unbanish <nom compte>\n";
-			printf "  Ote le banissement d'un compte.\n";
-			printf "  La commande est l'équivalent de banset <nom_compte> 0.\n";
-		} elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) {
-			printf "unblock <nom compte>\n";
-			printf "  Place le status d'un compte à 0 (Compte ok).\n";
-			printf "  La commande est l'équivalent de state <nom_compte> 0.\n";
-		} elsif ("version" =~ /^\Q$command/) {
-			printf "version\n";
-			printf "  Affiche la version du login-serveur.\n";
-		} elsif ("who" =~ /^\Q$command/) {
-			printf "who <nomcompte>\n";
-			printf "  Affiche les informations sur un compte.\n";
-		} elsif ("quit" =~ /^\Q$command/ ||
-		         (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'?\n";
-			printf "quit/end/exit\n";
-			printf "  Fin du programme d'administration.\n";
-		} else {
-			if ($receivedcommand ne "") {
-				printf "Commande inconnue [%s] pour l'aide. Affichage de toutes les commandes.\n", $receivedcommand;
-			}
-			print << "ENDOFAIDE";
- aide/help/?                             -- Affiche cet aide
- aide/help/? [commande]                  -- Affiche l'aide de la commande
- add <nomcompte> <sexe> <motdepasse>     -- Crée un compte (sans email)
- ban/banish aaaa/mm/jj hh:mm:ss <nomcompte>-- Change la date finale de banismnt
- banadd/ba <nomcompte> <modificateur>    -- Ajout/soustrait du temps à la
-   exemple: ba moncompte +1m-2mn1s-2y       date finale de banissement
- banset/bs <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la date fin de banisemnt
- banset/bs <nomcompte> 0                 -- Dé-banis un compte.
- block <nom compte>  -- Mets le status d'un compte à 5 (blocked by the GM Team)
- check <nomcompte> <motdepasse>          -- Vérifie un mot de passe d'un compte
- create <nomcompte> <sexe> <email> <motdepasse> -- Crée un compte (avec email)
- del <nomcompte>                         -- Supprime un compte
- email <nomcompte> <email>               -- Modifie l'e-mail d'un compte
- getcount                                -- Donne le nb de joueurs en ligne
- gm <nomcompte> [Niveau_GM]              -- Modifie le niveau de GM d'un compte
- id <nomcompte>                          -- Donne l'id d'un compte
- info <idcompte>                         -- Affiche les infos sur un compte
- kami <message>                          -- Envoi un message général (en jaune)
- kamib <message>                         -- Envoi un message général (en bleu)
- language <langue>                       -- Change la langue d'affichage.
- list/ls [Premier_id [Dernier_id] ]      -- Affiche une liste de comptes
- listBan/lsBan [Premier_id [Dernier_id] ]-- Affiche une liste de comptes
-                                            avec un statut ou bannis
- listGM/lsGM [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes GM
- listOK/lsOK [Premier_id [Dernier_id] ]  -- Affiche une liste de comptes
-                                            sans status et non bannis
- memo <nomcompte> <memo>                 -- Modifie le memo d'un compte
- name <idcompte>                         -- Donne le nom d'un compte
- passwd <nomcompte> <nouveaumotdepasse>  -- Change le mot de passe d'un compte
- quit/end/exit                           -- Fin du programme d'administation
- reloadGM                              -- Recharger le fichier de config des GM
- search <expression>                     -- Cherche des comptes
- search -e/-r/--expr/--regex <expression> -- Cherche des comptes par REGEX
- sex <nomcompte> <sexe>                  -- Modifie le sexe d'un compte
- state <nomcompte> <nouveaustatut> <messageerr7> -- Change le statut d'1 compte
- timeadd/ta <nomcompte> <modificateur>   -- Ajout/soustrait du temps à la
-   exemple: ta moncompte +1m-2mn1s-2y       limite de validité
- timeset/ts <nomcompte> aaaa/mm/jj [hh:mm:ss] -- Change la limite de validité
- timeset/ts <nomcompte> 0                -- limite de validité = illimitée
- unban/unbanish <nom compte>             -- Ote le banissement d'un compte
- unblock <nom compte>            -- Mets le status d'un compte à 0 (Compte ok)
- version                                 -- Donne la version du login-serveur
- who <nomcompte>                         -- Affiche les infos sur un compte
-ENDOFAIDE
-			printf(" Note: Pour les noms de compte avec des espaces, tapez \"<nom compte>\" (ou ').\n");
-		}
-	} else {
-		if ("aide" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			printf "aide/help/?\n";
-			printf "  Display the description of the commands\n";
-			printf "aide/help/? [command]\n";
-			printf "  Display the description of the specified command\n";
-		} elsif ("help" =~ /^\Q$command/) {
-			printf "aide/help/?\n";
-			printf "  Display the description of the commands\n";
-			printf "aide/help/? [command]\n";
-			printf "  Display the description of the specified command\n";
-		} elsif ("add" =~ /^\Q$command/ && $command ne "a") { # check 1 letter command: 'aide' or 'add'?
-			printf "add <account_name> <sex> <password>\n";
-			printf "  Create an account with the default email (a\@a.com).\n";
-			printf "  Concerning the sex, only the first letter is used (F or M).\n";
-			printf "  The e-mail is set to a\@a.com (default e-mail). It's like to have no e-mail.\n";
-			printf "  When the password is omitted,\n";
-			printf "  the input is done without displaying of the pressed keys.\n";
-			printf "  <example> add testname Male testpass\n";
-		} elsif ($command eq "ban" || ("banish" =~ /^\Q$command/ && length($command) >= 4)) {
-			printf "ban/banish yyyy/mm/dd hh:mm:ss <account_name>\n";
-			printf "  Changes the final date of a banishment of an account.\n";
-			printf "  The difference with banset is the position of the account name.\n";
-		} elsif (("banadd" =~ /^\Q$command/ || $command eq "ba") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			printf "banadd <account_name> <modifier>\n";
-			printf "  Adds or substracts time from the final date of a banishment of an account.\n";
-			printf "  Modifier is done as follows:\n";
-			printf "    Adjustment value (-1, 1, +1, etc...)\n";
-			printf "    Modified element:\n";
-			printf "      a or y: year\n";
-			printf "      m:  month\n";
-			printf "      j or d: day\n";
-			printf "      h:  hour\n";
-			printf "      mn: minute\n";
-			printf "      s:  second\n";
-			printf "  <example> banadd testname +1m-2mn1s-6y\n";
-			printf "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			printf "            and 6 years at the same time.\n";
-			printf "NOTE: If you modify the final date of a non-banished account,\n";
-			printf "      you fix the final date to (actual time +- adjustments)\n";
-		} elsif (("banset" =~ /^\Q$command/ || $command eq "bs") && $command ne "b") { # check 1 letter command: 'ba' or 'bs'?
-			printf "banset <account_name> yyyy/mm/dd [hh:mm:ss]\n";
-			printf "  Changes the final date of a banishment of an account.\n";
-			printf "  Default time: 23:59:59\n";
-			printf "banset <account_name> 0\n";
-			printf "  Set a non-banished account (0 = unbanished).\n";
-		} elsif ("block" =~ /^\Q$command/ && length($command) >= 2) {
-			printf "block <account name>\n";
-			printf "  Set state 5 (You have been blocked by the GM Team) to an account.\n";
-			printf "  Same command of state <account_name> 5.\n";
-		} elsif ("check" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			printf "check <account_name> <password>\n";
-			printf "  Check the validity of a password for an account.\n";
-			printf "  NOTE: Server will never sends back a password.\n";
-			printf "        It's the only method you have to know if a password is correct.\n";
-			printf "        The other method is to have a ('physical') access to the accounts file.\n";
-		} elsif ("create" =~ /^\Q$command/ && $command ne "c") { # check 1 letter command: 'check' or 'create'?
-			printf "create <account_name> <sex> <email> <password>\n";
-			printf "  Like the 'add' command, but with e-mail moreover.\n";
-			printf "  <example> create testname Male my\@mail.com testpass\n";
-		} elsif ("del" =~ /^\Q$command/ || "delete" =~ /^\Q$command/) {
-			printf "del <account_name>\n";
-			printf "  Remove an account.\n";
-			printf "  This order requires confirmation. After confirmation, the account is deleted.\n";
-		} elsif ("email" =~ /^\Q$command/ && $command ne "e") { # check 1 letter command: 'email', 'end' or 'exit'?
-			printf "email <account_name> <email>\n";
-			printf "  Modify the e-mail of an account.\n";
-		} elsif ("getcount" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			printf "getcount\n";
-			printf "  Give the number of players online on all char-servers.\n";
-		} elsif ("gm" =~ /^\Q$command/ && $command ne "g") { # check 1 letter command: 'getcount' or 'gm'?
-			printf "gm <account_name> [GM_level]\n";
-			printf "  Modify the GM level of an account.\n";
-			printf "  Default value remove GM level (GM level = 0).\n";
-			printf "  <example> gm testname 80\n";
-		} elsif ("id" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			printf "id <account_name>\n";
-			printf "  Give the id of an account.\n";
-		} elsif ("info" =~ /^\Q$command/ && $command ne "i") { # check 1 letter command: 'id' or 'info'?
-			printf "info <account_id>\n";
-			printf "  Display complete information of an account.\n";
-		} elsif ($command eq "kami") { # check all letters command: 'kami' or 'kamib'?
-			printf "kami <message>\n";
-			printf "  Sends a broadcast message on all map-server (in yellow).\n";
-		} elsif ($command eq "kamib") { # check all letters command: 'kami' or 'kamib'?
-			printf "kamib <message>\n";
-			printf "  Sends a broadcast message on all map-server (in blue).\n";
-		} elsif ("language" =~ /^\Q$command/ && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			printf("language <language>\n");
-			printf("  Change the language of displaying.\n");
-			printf("  Possible languages: Français or English.\n");
-		} elsif (("list" =~ /^\Q$command/ || $command eq "ls") && $command ne "l") { # check 1 letter command: 'list' or 'language'?
-			printf "list/ls [start_id [end_id]]\n";
-			printf "  Display a list of accounts.\n";
-			printf "  'start_id', 'end_id': indicate end and start identifiers.\n";
-			printf "  Research by name is not possible with this command.\n";
-			printf "  <example> list 10 9999999\n";
-		} elsif (("listban" =~ /^\Q$command/ || $command eq "lsban") && $command ne "l") { # need to specificaly write Ban to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listBan/lsBan [start_id [end_id]]\n";
-			printf "  Like list/ls, but only for accounts with state or banished.\n";
-		} elsif (("listgm" =~ /^\Q$command/ || $command eq "lsgm") && $command ne "l") { # need to specificaly write GM to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listGM/lsGM [start_id [end_id]]\n";
-			printf "  Like list/ls, but only for GM accounts.\n";
-		} elsif (("listok" =~ /^\Q$command/ || $command eq "lsok") && $command ne "l") { # need to specificaly write OK to have this list # check 1 letter command: 'list' or 'language'?
-			printf "listOK/lsOK [start_id [end_id]]\n";
-			printf "  Like list/ls, but only for accounts without state and not banished.\n";
-		} elsif ("memo" =~ /^\Q$command/) {
-			printf "memo <account_name> <memo>\n";
-			printf "  Modify the memo of an account.\n";
-			printf "  'memo': it can have until 253 characters (with spaces or not).\n";
-		} elsif ("name" =~ /^\Q$command/) {
-			printf "name <account_id>\n";
-			printf "  Give the name of an account.\n";
-		} elsif ("passwd" =~ /^\Q$command/ || "password" =~ /^\Q$command/) {
-			printf "passwd <account_name> <new_password>\n";
-			printf "  Change the password of an account.\n";
-			printf "  When new password is omitted,\n";
-			printf "  the input is done without displaying of the pressed keys.\n";
-		} elsif ("reloadgm" =~ /^\Q$command/) {
-			printf "reloadGM\n";
-			printf "  Reload GM configuration file\n";
-		} elsif ("search" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			printf "search <expression>\n";
-			printf "  Seek accounts.\n";
-			printf "  Displays the accounts whose names correspond.\n";
-			printf "search -r/-e/--expr/--regex <expression>\n";
-			printf "  Seek accounts by regular expression.\n";
-			printf "  Displays the accounts whose names correspond.\n";
-		} elsif ("sex" =~ /^\Q$command/ && $command ne "s" && # check 1 letter command: 'search', 'state' or 'sex'?
-		          $command ne "se") { # check 2 letters command: 'search' or 'sex'?
-			printf "sex <account_name> <sex>\n";
-			printf "  Modify the sex of an account.\n";
-			printf "  <example> sex testname Male\n";
-		} elsif ("state" =~ /^\Q$command/ && $command ne "s") { # check 1 letter command: 'search', 'state' or 'sex'?
-			printf "state <account_name> <new_state> <error_message_#7>\n";
-			printf "  Change the state of an account.\n";
-			printf "  'new_state': state is the state of the packet 0x006a + 1.\n";
-			printf "               The possibilities are:\n";
-			printf "               0 = Account ok\n";
-			printf "               1 = Unregistered ID\n";
-			printf "               2 = Incorrect Password\n";
-			printf "               3 = This ID is expired\n";
-			printf "               4 = Rejected from Server\n";
-			printf "               5 = You have been blocked by the GM Team\n";
-			printf "               6 = Your Game's EXE file is not the latest version\n";
-			printf "               7 = You are Prohibited to log in until...\n";
-			printf "               8 = Server is jammed due to over populated\n";
-			printf "               9 = No MSG\n";
-			printf "               100 = This ID has been totally erased\n";
-			printf "               all other values are 'No MSG', then use state 9 please.\n";
-			printf "  'error_message_#7': message of the code error 6\n";
-			printf "                      = Your are Prohibited to log in until... (packet 0x006a)\n";
-		} elsif (("timeadd" =~ /^\Q$command/ || $command eq "ta") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			printf "timeadd <account_name> <modifier>\n";
-			printf "  Adds or substracts time from the validity limit of an account.\n";
-			printf "  Modifier is done as follows:\n";
-			printf "    Adjustment value (-1, 1, +1, etc...)\n";
-			printf "    Modified element:\n";
-			printf "      a or y: year\n";
-			printf "      m:  month\n";
-			printf "      j or d: day\n";
-			printf "      h:  hour\n";
-			printf "      mn: minute\n";
-			printf "      s:  second\n";
-			printf "  <example> timeadd testname +1m-2mn1s-6y\n";
-			printf "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			printf "            and 6 years at the same time.\n";
-			printf "NOTE: You can not modify a unlimited validity limit.\n";
-			printf "      If you want modify it, you want probably create a limited validity limit.\n";
-			printf "      So, at first, you must set the validity limit to a date/time.\n";
-		} elsif (("timeset" =~ /^\Q$command/ || $command eq "ts") && $command ne "t") { # check 1 letter command: 'ta' or 'ts'?
-			printf "timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n";
-			printf "  Changes the validity limit of an account.\n";
-			printf "  Default time: 23:59:59\n";
-			printf "timeset <account_name> 0\n";
-			printf "  Gives an unlimited validity limit (0 = unlimited).\n";
-		} elsif ($command eq "unban" || ("unbanish" =~ /^\Q$command/ && length($command) >= 4)) {
-			printf "unban/unbanish <account name>\n";
-			printf "  Remove the banishment of an account.\n";
-			printf "  This command works like banset <account_name> 0.\n";
-		} elsif ("unblock" =~ /^\Q$command/ && length($command) >= 4) {
-			printf "unblock <account name>\n";
-			printf "  Set state 0 (Account ok) to an account.\n";
-			printf "  This command works like state <account_name> 0.\n";
-		} elsif ("version" =~ /^\Q$command/) {
-			printf "version\n";
-			printf "  Display the version of the login-server.\n";
-		} elsif ("who" =~ /^\Q$command/) {
-			printf "who <account_name>\n";
-			printf "  Displays complete information of an account.\n";
-		} elsif ("quit" =~ /^\Q$command/ ||
-		         (("end" =~ /^\Q$command/ || "exit" =~ /^\Q$command/) && $command ne "e")) { # check 1 letter command: 'email', 'end' or 'exit'?\n";
-			printf "quit/end/exit\n";
-			printf "  End of the program of administration.\n";
-		} else {
-			if ($receivedcommand ne "") {
-				printf "Unknown command [%s] for help. Displaying of all commands.\n", $receivedcommand;
-			}
-			print << "ENDOFHELP";
- aide/help/?                          -- Display this help
- aide/help/? [command]                -- Display the help of the command
- add <account_name> <sex> <password>  -- Create an account with default email
- ban/banish yyyy/mm/dd hh:mm:ss <account_name> -- Change final date of a ban
- banadd/ba <account_name> <modifier>  -- Add or substract time from the final
-   example: ba apple +1m-2mn1s-2y        date of a banishment of an account
- banset/bs <account_name> yyyy/mm/dd [hh:mm:ss] -- Change final date of a ban
- banset/bs <account_name> 0           -- Un-banish an account
- block <account name>    -- Set state 5 (blocked by the GM Team) to an account
- check <account_name> <password>      -- Check the validity of a password
- create <account_name> <sex> <email> <passwrd> -- Create an account with email
- del <account_name>                   -- Remove an account
- email <account_name> <email>         -- Modify an email of an account
- getcount                             -- Give the number of players online
- gm <account_name> [GM_level]         -- Modify the GM level of an account
- id <account_name>                    -- Give the id of an account
- info <account_id>                    -- Display all information of an account
- kami <message>                       -- Sends a broadcast message (in yellow)
- kamib <message>                      -- Sends a broadcast message (in blue)
- language <language>                  -- Change the language of displaying.
- list/ls [First_id [Last_id]]         -- Display a list of accounts
- listBan/lsBan [First_id [Last_id]]   -- Display a list of accounts
-                                         with state or banished
- listGM/lsGM [First_id [Last_id]]     -- Display a list of GM accounts
- listOK/lsOK [First_id [Last_id]]     -- Display a list of accounts
-                                         without state and not banished
- memo <account_name> <memo>           -- Modify the memo of an account
- name <account_id>                    -- Give the name of an account
- passwd <account_name> <new_password> -- Change the password of an account
- quit/end/exit                        -- End of the program of administation
- reloadGM                             -- Reload GM configuration file
- search <expression>                  -- Seek accounts
- search -e/-r/--expr/--regex <expressn> -- Seek accounts by regular-expression
- sex <nomcompte> <sexe>               -- Modify the sex of an account
- state <account_name> <new_state> <error_message_#7> -- Change the state
- timeadd/ta <account_name> <modifier> -- Add or substract time from the
-   example: ta apple +1m-2mn1s-2y        validity limit of an account
- timeset/ts <account_name> yyyy/mm/dd [hh:mm:ss] -- Change the validify limit
- timeset/ts <account_name> 0         -- Give a unlimited validity limit
- unban/unbanish <account name>       -- Remove the banishment of an account
- unblock <account name>              -- Set state 0 (Account ok) to an account
- version                             -- Gives the version of the login-server
- who <account_name>                  -- Display all information of an account
-ENDOFHELP
-			printf(" Note: To use spaces in an account name, type \"<account name>\" (or ').\n");
-		}
-	}
-
-	return 0;
-}
-#--------------------------------------------------------------------------
-
-# Sub-function: Displaying of the accounts list
-sub listaccount() {
-	my($st, $ed, $listflag) = @_;
-	my($i);
-	my($n) = (0);
-	#      0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
-	if ($defaultlanguage eq "F") {
-		print " id_compte GM nom_utilisateur         sexe   count statut\n";
-	} else {
-		print "account_id GM user_name               sex    count state\n";
-	}
-	print "-------------------------------------------------------------------------------\n";
-	while(1) {
-		print $so pack("vV2", 0x7920, $st, $ed);
-		$so->flush();
-		$buf = readso(4);
-		if (unpack("v", $buf) != 0x7921) {
-			if ($defaultlanguage eq "F") {
-				print "Problème de connexion au serveur (réponse incorrecte).\n";
-			} else {
-				print "Connection error to the server (incorrect answer).\n";
-			}
-			exit(10);
-		}
-		my($len) = unpack("x2v", $buf);
-		last if ($len <= 4);
-		for($i = 4; $i < $len; $i += 38) {
-			my(@dat) = unpack("VCa24cVV", readso(38));
-			$st = $dat[0] + 1;
-			if ($listflag == 0 ||
-			    ($listflag == 1 && $dat[1] > 0) || # check GM flag
-			    ($listflag == 3 && $dat[5] != 0) || # check with state or banished
-			    ($listflag == 4 && $dat[5] == 0)) { # check without state and not banished
-				printf "%10d %2s %-24s%-5s %6d %-27s\n", $dat[0],
-				        ($dat[1] == 0 ? "  " : $dat[1]),
-				        $dat[2],
-				        ($defaultlanguage eq "F" ? ("Femme","Male","Servr")[$dat[3]] : ("Femal","Male","Servr")[$dat[3]]),
-				        $dat[4],
-				        (($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"),
-				         "Unregistered ID",
-				         "Incorrect Password",
-				         "This ID is expired",
-				         "Rejected from Server",
-				         "Blocked by the GM Team", # You have been blocked by the GM Team
-				         "Your EXE file is too old", # Your Game's EXE file is not the latest version
-				         "Banishement or\n                                                   Prohibited to login until %s", # You are Prohibited to log in until %s
-				         "Server is over populated", # Server is jammed due to over populated
-				         "No MSG",
-				         "This ID is totally erased")[$dat[5] == 100 ? 10 : $dat[5]]; # This ID has been totally erased
-				$n++;
-			}
-		}
-	}
-	if ($defaultlanguage eq "F") {
-		if ($n == 0) {
-			print "Aucun compte trouvé.\n";
-		} elsif ($n == 1) {
-			print "1 compte trouvé.\n";
-		} else {
-			print "$n comptes trouvés.\n";
-		}
-	} else {
-		if ($n == 0) {
-			print "No account found.\n";
-		} elsif ($n == 1) {
-			print "1 account found.\n";
-		} else {
-			print "$n accounts found.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: add an account with the default e-mail
-sub addaccount() {
-	my($userid, $sex, $passwd) = @_;
-	if ($userid eq "" || !defined($userid)) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> add nomtest Male motdepassetest\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> add testname Male testpass\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-#	if ($userid =~ /[^A-Za-z0-9\@-_]/) {
-#		if ($defaultlanguage eq "F") {
-#			print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n";
-#		} else {
-#			print "Illegal character found in the account name ".$`."[${&}]${'}\n";
-#		}
-#		return 101;
-#	}
-	$sex = uc(substr($sex, 0, 1));
-	if ($sex !~ /^[MF]$/) {
-		if ($defaultlanguage eq "F") {
-			print "Sexe incorrect [$sex]. Entrez M ou F svp.\n";
-		} else {
-			print "Illegal gender [$sex]. Please input M or F.\n";
-		}
-		return 103;
-	}
-	if ($passwd eq "") {
-		return 108 if (($passwd = typepasswd()) eq "");
-	}
-	if (verify_password($passwd) == 0) {
-		return 104;
-	}
-	print $so pack("va24a24a1a40", 0x7930, $userid, $passwd, $sex, "");
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7931) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 106;
-	}
-	$buf = readso(28);
-	if (unpack("V", $buf) == -1 || unpack("V", $buf) == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec à la création du compte [$userid]. Un compte identique existe déjà.\n";
-		} else {
-			print "Account [$userid] creation failed. Same account already exists.\n";
-		}
-		return 107;
-	} else {
-		if ($defaultlanguage eq "F") {
-			printf "Compte [$userid] créé avec succès [id: %d].\n", unpack("V",$buf);
-		} else {
-			printf "Account [$userid] is successfully created [id: %d].\n", unpack("V",$buf);
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: add an account with an e-mail
-sub createaccount() {
-	my($userid, $sex, $email, $passwd) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> create nomtest Male mon\@email.com motdepassetest\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> create testname Male my\@mail.com testpass\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-#	if ($userid =~ /[^A-Za-z0-9\@-_]/) {
-#		if ($defaultlanguage eq "F") {
-#			print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n";
-#		} else {
-#			print "Illegal character found in the account name ".$`."[${&}]${'}\n";
-#		}
-#		return 101;
-#	}
-	$sex = uc(substr($sex, 0, 1));
-	if ($sex !~ /^[MF]$/) {
-		if ($defaultlanguage eq "F") {
-			print "Sexe incorrect [$sex]. Entrez M ou F svp.\n";
-		} else {
-			print "Illegal gender [$sex]. Please input M or F.\n";
-		}
-		return 103;
-	}
-	if (length($email) < 3) {
-		if ($defaultlanguage eq "F") {
-			print "Email trop courte [$email]. Entrez une e-mail valide svp.\n";
-		} else {
-			print "Email is too short [$email]. Please input a valid e-mail.\n";
-		}
-		return 109;
-	}
-	if (length($email) > 39) {
-		if ($defaultlanguage eq "F") {
-			print "Email trop longue [$email]. Entrez une e-mail de 39 caractères maximum svp.\n";
-		} else {
-			print "Email is too long [$email]. Please input an e-mail with 39 bytes at the most.\n";
-		}
-		return 109;
-	}
-	if (verify_email($email) == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Email incorrecte [$email]. Entrez une e-mail valide svp.\n";
-		} else {
-			print "Invalid email [$email]. Please input a valid e-mail.\n";
-		}
-		return 109;
-	}
-	if ($passwd eq "") {
-		return 108 if (($passwd = typepasswd()) eq "");
-	}
-	if (verify_password($passwd) == 0) {
-		return 104;
-	}
-	print $so pack("va24a24a1a40", 0x7930, $userid, $passwd, $sex, $email);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7931) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 106;
-	}
-	$buf = readso(28);
-	if (unpack("V", $buf) == -1 || unpack("V", $buf) == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec à la création du compte [$userid]. Un compte identique existe déjà.\n";
-		} else {
-			print "Account [$userid] creation failed. Same account already exists.\n";
-		}
-		return 107;
-	} else {
-		if ($defaultlanguage eq "F") {
-			printf "Compte [$userid] créé avec succès [id: %d].\n", unpack("V",$buf);
-		} else {
-			printf "Account [$userid] is successfully created [id: %d].\n", unpack("V",$buf);
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: deletion of an account
-sub delaccount() {
-	my($userid) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> del nomtestasupprimer\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> del testnametodelete\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if ($defaultlanguage eq "F") {
-		print "** Etes-vous vraiment sûr de vouloir SUPPRIMER le compte [$userid]? (o/n) ";
-	} else {
-		print "** Are you really sure to DELETE account [$userid]? (y/n) ";
-	}
-	if (lc(substr(<STDIN>, 0, 1)) !~ /[oy]/) {
-		if ($defaultlanguage eq "F") {
-			print "Suppression annulée\n.";
-		} else {
-			print "Deletion canceled\n";
-		}
-		return 121;
-	}
-	print $so pack("va24", 0x7932, $userid);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7933) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 122;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec de la suppression du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] deletion failed. Account doesn't exist.\n";
-		}
-		return 123;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Compte [$name][id: $id2] SUPPRIME avec succès.\n";
-		} else {
-			print "Account [$name][id: $id2] is successfully DELETED.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: modification of a password
-sub changepasswd() {
-	my($userid, $passwd) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> passwd nomtest nouveaumotdepasse\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> passwd testname newpassword\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if ($passwd eq "") {
-		return 134 if (($passwd = typepasswd()) eq "");
-	}
-	if (verify_password($passwd) == 0) {
-		return 131;
-	}
-	print $so pack("va24a24", 0x7934, $userid,$passwd);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7935) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 132;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec de la modification du mot de passe du compte [$userid].\n";
-			print "Le compte [$userid] n'existe pas.\n";
-		} else {
-			print "Account [$userid] password changing failed.\n";
-			print "Account [$userid] doesn't exist.\n";
-		}
-		return 133;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Modification du mot de passe du compte [$name][id: $id2] réussie.\n";
-		} else {
-			print "Account [$name][id: $id2] password successfully changed.\n";
-		}
-	}
-	return 130;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: modification of an account e-mail
-sub changeemail() {
-	my($userid, $email) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> email testname nouveauemail\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> email testname newemail\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if (length($email) < 3) {
-		if ($defaultlanguage eq "F") {
-			print "Email trop courte [$email]. Entrez une e-mail valide svp.\n";
-		} else {
-			print "Email is too short [$email]. Please input a valid e-mail.\n";
-		}
-		return 109;
-	}
-	if (length($email) > 39) {
-		if ($defaultlanguage eq "F") {
-			print "Email trop longue [$email]. Entrez une e-mail de 39 caractères maximum svp.\n";
-		} else {
-			print "Email is too long [$email]. Please input an e-mail with 39 bytes at the most.\n";
-		}
-		return 109;
-	}
-	if (verify_email($email) == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Email incorrect [$email]. Entrez une e-mail valide svp.\n";
-		} else {
-			print "Invalid email [$email]. Please input a valid e-mail.\n";
-		}
-		return 109;
-	}
-	print $so pack("va24a40", 0x7940, $userid, $email);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7941) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 162;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec de la modification de l'e-mail du compte [$userid].\n";
-			print "Le compte [$userid] n'existe pas.\n";
-		} else {
-			print "Account [$userid] e-mail changing failed.\n";
-			print "Account [$userid] doesn't exist.\n";
-		}
-		return 133;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Modification de l'e-mail du compte [$name][id: $id2] réussie.\n";
-		} else {
-			print "Account [$name][id: $id2] e-mail successfully changed.\n";
-		}
-	}
-	return 160;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: search of accounts
-sub searchaccount() {
-	my($p1, $p2) = @_;
-	my($exp) = ("");
-	if ($p1 eq "-e" || $p1 eq "-r" || $p1 eq "--regex" || $p1 eq "--expr") {
-		if ($p2 eq "") {
-			if ($defaultlanguage eq "F") {
-				print "Entrez une expression régulière ou utilisez 'ls' pour avoir tous les comptes.\n";
-			} else {
-				print "Input a regular expression or use 'ls' to obtain all accounts.\n";
-			}
-			return 141;
-		}
-		$exp = $p2;
-	} else {
-		if ($p1 eq "") {
-			if ($defaultlanguage eq "F") {
-				print "Entrez une chaîne ou utilisez 'ls' pour avoir tous les comptes.\n";
-			} else {
-				print "Input a string or use 'ls' to obtain all accounts.\n";
-			}
-			return 141;
-		}
-		my($c) = 0;
-		$exp = lc($p1);
-		$exp =~ s/([\@])/\\$1/g;
-		$c += $exp =~ s/([\-\[\]])/\\$1/g;
-		$c += $exp =~ s/([\*\?])/.$1/g;
-		$c += $exp =~ s/\\\[(.)\\\-(.)\\\]/[$1-$2]/g;
-		$exp = "^$exp\$" if $c;
-	}
-	if (eval{ "" =~ /$exp/; }, $@) {
-		if ($defaultlanguage eq "F") {
-			print "Expression régulière non reconnue.\n";
-		} else {
-			print "Regular-Expression compiling failed.\n";
-		}
-		return 141;
-	}
-	my($i);
-	my($n, $st) = (0, 0);
-	#      0123456789 01 01234567890123456789012301234 012345 0123456789012345678901234567
-	if ($defaultlanguage eq "F") {
-		print " id_compte GM nom_utilisateur         sexe   count statut\n";
-	} else {
-		print "account_id GM user_name               sex    count state\n";
-	}
-	print "-------------------------------------------------------------------------------\n";
-	while(1) {
-		print $so pack("vV2", 0x7920, $st, 0);
-		$so->flush();
-		$buf = readso(4);
-		if (unpack("v", $buf) != 0x7921) {
-			if ($defaultlanguage eq "F") {
-				print "Problème de connexion au serveur (réponse incorrecte).\n";
-			} else {
-				print "Connection error to the server (incorrect answer).\n";
-			}
-			exit(10);
-		}
-		my($len) = unpack("x2v", $buf);
-		last if ($len <= 4);
-		for($i = 4; $i < $len; $i += 38) {
-			my(@dat) = unpack("VCa24cVV", readso(38));
-			$st = $dat[0] + 1;
-			next if (lc($dat[2]) !~ /$exp/);
-			printf "%10d %2s %-24s%-5s %6d %-27s\n", $dat[0],
-			        ($dat[1] == 0 ? "  " : $dat[1]),
-			        $dat[2],
-			        ($defaultlanguage eq "F" ? ("Femme","Male","Servr")[$dat[3]] : ("Femal","Male","Servr")[$dat[3]]),
-			        $dat[4],
-			        (($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"),
-			         "Unregistered ID",
-			         "Incorrect Password",
-			         "This ID is expired",
-			         "Rejected from Server",
-			         "Blocked by the GM Team", # You have been blocked by the GM Team
-			         "Your EXE file is too old", # Your Game's EXE file is not the latest version
-			         "Banishement or\n                                                   Prohibited to login until %s", # You are Prohibited to log in until %s
-			         "Server is over populated", # Server is jammed due to over populated
-			         "No MSG",
-			         "This ID is totally erased")[$dat[5] == 100 ? 10 : $dat[5]]; # This ID has been totally erased
-			$n++;
-		}
-	}
-	if ($defaultlanguage eq "F") {
-		if ($n == 0) {
-			print "Aucun compte trouvé.\n";
-		} elsif ($n == 1) {
-			print "1 compte trouvé.\n";
-		} else {
-			print "$n comptes trouvés.\n";
-		}
-	} else {
-		if ($n == 0) {
-			print "No account found.\n";
-		} elsif ($n == 1) {
-			print "1 account found.\n";
-		} else {
-			print "$n accounts found.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: modify the sex of an account
-sub changesex() {
-	my($userid, $sex) = @_;
-	if ($userid eq "" || !defined($userid)) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> sex nomtest Male\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> sex testname Male\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-#	if ($userid =~ /[^A-Za-z0-9\@-_]/) {
-#		if ($defaultlanguage eq "F") {
-#			print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n";
-#		} else {
-#			print "Illegal character found in the account name ".$`."[${&}]${'}\n";
-#		}
-#		return 101;
-#	}
-	$sex = uc(substr($sex, 0, 1));
-	if ($sex !~ /^[MF]$/) {
-		if ($defaultlanguage eq "F") {
-			print "Sexe incorrect [$sex]. Entrez M ou F svp.\n";
-		} else {
-			print "Illegal gender [$sex]. Please input M or F.\n";
-		}
-		return 103;
-	}
-	print $so pack("va24a1", 0x793c, $userid, $sex);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x793d) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement du sexe du compte [$userid].\n";
-			print "Le compte n'existe pas ou le sexe est déjà celui demandé.\n";
-		} else {
-			print "Account [$userid] sex changing failed.\n";
-			print "Account doesn't exist or the sex is already the good sex.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Sexe du compte [$name][id: $id2] changé avec succès.\n";
-		} else {
-			print "Account [$name][id: $id2] sex successfully changed.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: modify the GM level of an account
-sub changegmlevel() {
-	my($userid, $gm_level) = @_;
-	if ($userid eq "" || !defined($userid)) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> gm nomtest 80\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> gm testname 80\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-#	if ($userid =~ /[^A-Za-z0-9\@-_]/) {
-#		if ($defaultlanguage eq "F") {
-#			print "Caractère interdit trouvé dans le nom du compte ".$`."[${&}]${'}\n";
-#		} else {
-#			print "Illegal character found in the account name ".$`."[${&}]${'}\n";
-#		}
-#		return 101;
-#	}
-	$gm_level = int($gm_level);
-	if ($gm_level < 0 || $gm_level > 99) {
-		if ($defaultlanguage eq "F") {
-			print "Niveau de GM incorrect [$gm_level]. Entrez une valeur de 0 à 99 svp.\n";
-		} else {
-			print "Illegal GM level [$gm_level]. Please input a value from 0 to 99.\n";
-		}
-		return 103;
-	}
-	print $so pack("va24C", 0x793e, $userid, $gm_level);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x793f) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement du niveau de GM du compte [$userid].\n";
-			print "Le compte n'existe pas, le niveau de GM est déjà celui demandé,\n";
-			print "ou il est impossible de modifier le fichier des comptes GM.\n";
-		} else {
-			print "Account [$userid] GM level changing failed.\n";
-			print "Account doesn't exist, the GM level is already the good GM level,\n";
-			print "or it's impossible to modify the GM accounts file.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Niveau de GM du compte [$name][id: $id2] changé avec succès.\n";
-		} else {
-			print "Account [$name][id: $id2] GM level successfully changed.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Modification of a state
-sub changestate {
-	my($userid, $s, $error_message) = @_;
-	# Valid values: 0: ok, or value of the 0x006a packet + 1
-	if ($s eq "" || (($s < 0 || $s > 9) && $s != 100)) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez une des valeurs suivantes svp:\n";
-			print "  0 = Compte ok             6 = Your Game's EXE file is not the latest version\n";
-		} else {
-			print "Please input one of these values:\n";
-			print "  0 = Account ok            6 = Your Game's EXE file is not the latest version\n";
-		}
-		print "  1 = Unregistered ID       7 = You are Prohibited to log in until %s\n";
-		print "  2 = Incorrect Password    8 = Server is jammed due to over populated\n";
-		print "  3 = This ID is expired    9 = No MSG\n";
-		print "  4 = Rejected from Server  100 = This ID has been totally erased\n";
-		print "  5 = You have been blocked by the GM Team\n";
-		if ($defaultlanguage eq "F") {
-			print "<exemples> state nomtest 5\n";
-			print "           state nomtest 7 fin de votre ban\n";
-			print "           block <nom du compte>\n";
-			print "           unblock <nom du compte>\n";
-		} else {
-			print "<examples> state testname 5\n";
-			print "           state testname 7 end of your ban\n";
-			print "           block <account name>\n";
-			print "           unblock <account name>\n";
-		}
-		return 151;
-	}
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemples> state nomtest 5\n";
-			print "           state nomtest 7 fin de votre ban\n";
-			print "           block <nom du compte>\n";
-			print "           unblock <nom du compte>\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<examples> state testname 5\n";
-			print "           state testname 7 end of your ban\n";
-			print "           block <account name>\n";
-			print "           unblock <account name>\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if ($s != 7) {
-		$error_message = "-";
-	} else {
-		if (length($error_message) < 1) {
-			if ($defaultlanguage eq "F") {
-				print "Message d'erreur trop court. Entrez un message de 1-19 caractères.\n";
-			} else {
-				print "Error message is too short. Please input a message of 1-19 bytes.\n";
-			}
-			return 102;
-		}
-		if (length($error_message) > 19) {
-			if ($defaultlanguage eq "F") {
-				print "Message d'erreur trop long. Entrez un message de 1-19 caractères.\n";
-			} else {
-				print "Error message is too long. Please input a message of 1-19 bytes.\n";
-			}
-			return 102;
-		}
-	}
-	print $so pack("va24Va20", 0x7936, $userid, $s, $error_message);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7937) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(32);
-	my(@dat) = unpack("Va24V", $buf);
-	while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) {
-		chop($dat[1]);
-	};
-	if ($dat[0] != -1 && $dat[0] != 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Statut du compte [$dat[1]][id: $dat[0]] changé avec succès en [";
-		} else {
-			print "Account [$dat[1]][id: $dat[0]] state successfully changed in [";
-		}
-		print ((($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"),
-		  "Unregistered ID",
-		  "Incorrect Password",
-		  "This ID is expired",
-		  "Rejected from Server",
-		  "You have been blocked by the GM Team",
-		  "Your Game's EXE file is not the latest version",
-		  "You are Prohibited to log in until %s",
-		  "Server is jammed due to over populated",
-		  "No MSG",
-		  "This ID has been totally erased")[$dat[2] == 100 ? 10 : $dat[2]]);
-		print "].\n";
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement du statut du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] state changing failed. Account doesn't exist.\n";
-		}
-	}
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Displaying of the number of online players
-sub getlogincount {
-	# Request to the login-server
-	print $so pack("v", 0x7938);
-	$so->flush();
-
-	$buf = readso(4);
-	# Connection failed
-	if (unpack("v", $buf) != 0x7939) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		exit(3);
-	}
-
-	# Get length of the received packet
-	my($len) = unpack("x2v", $buf) - 4;
-
-	# Read information of the servers
-	if ($len < 1) {
-		if ($defaultlanguage eq "F") {
-			printf "  Aucun serveur n'est connecté au login serveur.\n";
-		} else {
-			printf "  No server is connected to the login-server.\n";
-		}
-	} else {
-		my(@slist) = ();
-		for(; $len > 0; $len -= 32) {
-			my($name, $count) = unpack("x6 a20 V", readso(32));
-			$name = substr($name, 0, index($name, "\0"));
-			push @slist, [ $name, $count ];
-		}
-		# Displaying of result
-		my($i);
-		if ($defaultlanguage eq "F") {
-			printf "  Nombre de joueurs en ligne (serveur: nb):\n";
-		} else {
-			printf "  Number of online players (server: number).\n";
-		}
-		foreach $i(@slist) {
-			printf "    %-20s : %5d\n", $i->[0], $i->[1];
-		}
-	}
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Modification of a memo field
-sub changememo {
-	my($userid, $memo) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> memo nomtest nouveau memo\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> memo testname new memo\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if (length($memo) > 254) {
-		if ($defaultlanguage eq "F") {
-			print "Mémo trop long (".length($memo)." caractères).\n";
-			print "Entrez un mémo de 254 caractères maximum svp.\n";
-		} else {
-			print "Memo is too long (".length($memo)." characters).\n";
-			print "Please input a memo of 254 bytes at the maximum.\n";
-		}
-		return 102;
-	}
-	if (length($memo) == 0) {
-		print $so pack("va24v", 0x7942, $userid, 0);
-	} else {
-		print $so pack("va24va".length($memo), 0x7942, $userid, length($memo), $memo);
-	}
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7943) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement du mémo du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] memo changing failed. Account doesn't exist.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Mémo du compte [$name][id: $id2] changé avec succès.\n";
-		} else {
-			print "Account [$name][id: $id2] memo successfully changed.\n";
-		}
-	}
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Request to obtain an account id
-sub idaccount() {
-	my($userid) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> id nomtest\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> id testname\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	print $so pack("va24", 0x7944, $userid);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7945) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 122;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Impossible de trouver l'id du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Unabled to find the account [$userid] id. Account doesn't exist.\n";
-		}
-		return 123;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Le compte [$name] a pour id: $id2.\n";
-		} else {
-			print "The account [$name] have the id: $id2.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Request to obtain an account name
-sub nameaccount() {
-	my($id) = @_;
-	if ($id < 0) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un id ayant une valeur positive svp.\n";
-		} else {
-			print "Please input a positive value for the id.\n";
-		}
-		return 136;
-	}
-	print $so pack("vV", 0x7946, $id);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7947) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 122;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if (length($name) == 0 || $name eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Impossible de trouver le nom du compte [id: $id2]. Le compte n'existe pas.\n";
-		} else {
-			print "Unabled to find the account [id: $id2] name. Account doesn't exist.\n";
-		}
-		return 123;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Le compte [id: $id2] a pour nom: $name.\n";
-		} else {
-			print "The account [id: $id2] have the name: $name.\n";
-		}
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Set a validity limit of an account
-sub timesetaccount() {
-	my($userid, $date, $time) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple>: timeset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n";
-			print "           timeset <nom_du_compte> 0    (0 = illimité)\n";
-			printf "          Heure par défaut [hh:mm:ss]: 23:59:59\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example>: timeset <account_name> yyyy/mm/dd [hh:mm:ss]\n";
-			print "           timeset <account_name> 0   (0 = unlimited)\n";
-			printf "          Default time [hh:mm:ss]: 23:59:59\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	my($year, $month, $day) = split(/[.\-\/]/, $date);
-	my($hour, $minute, $second) = split(/:/, $time);
-	if ($time eq "") {
-		$hour = 23;
-		$minute = 59;
-		$second = 59;
-	}
-	my($timestamp);
-	if ($year eq "" ||
-	    ($year != 0 && ($month eq "" || $day eq "" || $hour eq "" || $minute eq "" || $second eq ""))) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n";
-		} else {
-			print "Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n";
-		}
-		return 102;
-	}
-	if ($year == 0) {
-		$timestamp = 0;
-	} else {
-		if ($year < 70) {
-			$year = $year + 100;
-		}
-		if ($year >= 1900) {
-			$year = $year - 1900;
-		}
-		if ($month < 1 || $month > 12) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un mois correct svp (entre 1 et 12).\n";
-			} else {
-				print "Please give a correct value for the month (from 1 to 12).\n";
-			}
-			return 102;
-		}
-		$month = $month - 1;
-		if ($day < 1 || $day > 31) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un jour correct svp (entre 1 et 31).\n";
-			} else {
-				print "Please give a correct value for the day (from 1 to 31).\n";
-			}
-			return 102;
-		}
-		if ((($month == 3 || $month == 5 || $month == 8 || $month == 10) && $day > 30) ||
-		    ($month == 1 && $day > 29)) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un jour correct en fonction du mois svp.\n";
-			} else {
-				print "Please give a correct value for a day of this month.\n";
-			}
-			return 102;
-		}
-		if ($hour < 0 || $hour > 23) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez une heure correcte svp (entre 0 et 23).\n";
-			} else {
-				print "Please give a correct value for the hour (from 0 to 23).\n";
-			}
-			return 102;
-		}
-		if ($minute < 0 || $minute > 59) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez des minutes correctes svp (entre 0 et 59).\n";
-			} else {
-				print "Please give a correct value for the minutes (from 0 to 59).\n";
-			}
-			return 102;
-		}
-		if ($second < 0 || $second > 59) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez des secondes correctes svp (entre 0 et 59).\n";
-			} else {
-				print "Please give a correct value for the seconds (from 0 to 59).\n";
-			}
-			return 102;
-		}
-		$timestamp = POSIX::mktime($second, $minute, $hour, $day, $month, $year, 0, 0, -1); # -1: no winter/summer time modification
-		if ($timestamp == undef) {
-			if ($defaultlanguage eq "F") {
-				print "Date incorrecte.\n";
-				print "Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n";
-			} else {
-				print "Invalid date.\n";
-				print "Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n";
-			}
-			return 102;
-		}
-	}
-
-	print $so pack("va24V", 0x7948, $userid, $timestamp);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7949) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(32);
-	my(@dat) = unpack("Va24V", $buf);
-	while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) {
-		chop($dat[1]);
-	};
-	if ($dat[0] != -1 && $dat[0] != 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Limite de validité du compte [$dat[1]][id: $dat[0]] changée avec succès ".
-			($dat[2] == 0 ? "en [illimité].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2])));
-		} else {
-			print "Validity Limit of the account [$dat[1]][id: $dat[0]] successfully changed ".
-			($dat[2] == 0 ? "to [unlimited].\n" : "to be until ".(POSIX::ctime($dat[2])));
-		}
-		# localtime($dat[2]) is also possible to display instead of POSIX::ctime.
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement de la validité du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] validity limit changing failed. Account doesn't exist.\n";
-		}
-	}
-
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Add/substract time to the validity limit of an account
-sub timeaddaccount() {
-	my($userid, $modif) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "  <exemple> timeadd nomtest +1m-2mn1s-6y\n";
-			print "            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n";
-			print "            et 6 ans dans le même temps.\n";
-		} else {
-			print "Please input an account name.\n";
-			print "  <example> timeadd testname +1m-2mn1s-6y\n";
-			print "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			print "            and 6 years at the same time.\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	my($year, $month, $day) = (0, 0 ,0);
-	my($hour, $minute, $second) = (0, 0 ,0);
-
-	$modif = lc($modif);
-	while (length($modif) > 0) {
-		my($value) = int($modif);
-		if ($value == 0) {
-			$modif = substr($modif, 1);
-		} else {
-			if (substr($modif, 0, 1) =~ /[\-\+]/) {
-				$modif = substr($modif, 1);
-			}
-			while (length($modif) > 0 && substr($modif, 0, 1) =~ /[0-9]/) {
-				$modif = substr($modif, 1);
-			}
-			if (index($modif, "s") == 0) {
-				$second = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "mn") == 0) {
-				$minute = $value;
-				$modif = substr($modif, 2);
-			} elsif (index($modif, "h") == 0) {
-				$hour = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "d") == 0 || index($modif, "j") == 0) {
-				$day = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "m") == 0) {
-				$month = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "y") == 0 || index($modif, "a") == 0) {
-				$year = $value;
-				$modif = substr($modif, 1);
-			} else {
-				$modif = substr($modif, 1);
-			}
-		}
-	}
-
-	if ($defaultlanguage eq "F") {
-		print " année:   $year\n";
-		print " mois:    $month\n";
-		print " jour:    $day\n";
-		print " heure:   $hour\n";
-		print " minute:  $minute\n";
-		print " seconde: $second\n";
-	} else {
-		print " year:   $year\n";
-		print " month:  $month\n";
-		print " day:    $day\n";
-		print " hour:   $hour\n";
-		print " minute: $minute\n";
-		print " second: $second\n";
-	}
-
-	if ($year == 0 && $month == 0 && $day == 0 && $hour == 0 && $minute == 0 && $second == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Vous devez entrer un ajustement avec cette commande, svp:\n";
-			print "  Valeur d'ajustement (-1, 1, +1, etc...)\n";
-			print "  Element modifié:\n";
-			print "    a ou y: année\n";
-			print "    m:      mois\n";
-			print "    j ou d: jour\n";
-			print "    h:      heure\n";
-			print "    mn:     minute\n";
-			print "    s:      seconde\n";
-			print "  <exemple> timeadd nomtest +1m-2mn1s-6y\n";
-			print "            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n";
-			print "            et 6 ans dans le même temps.\n";
-		} else {
-			print "Please give an adjustment with this command:\n";
-			print "  Adjustment value (-1, 1, +1, etc...)\n";
-			print "  Modified element:\n";
-			print "    a or y: year\n";
-			print "    m:      month\n";
-			print "    j or d: day\n";
-			print "    h:       hour\n";
-			print "    mn:      minute\n";
-			print "    s:       second\n";
-			print "  <example> timeadd testname +1m-2mn1s-6y\n";
-			print "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			print "            and 6 years at the same time.\n";
-		}
-		return 137;
-	}
-	if ($year > 127 || $year < -127) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement d'années correct (de -127 à 127), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the years (from -127 to 127).\n";
-		}
-		return 137;
-	}
-	if ($month > 255 || $month < -255) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de mois correct (de -255 à 255), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the months (from -255 to 255).\n";
-		}
-		return 137;
-	}
-	if ($day > 32767 || $day < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the days (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($hour > 32767 || $hour < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the hours (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($minute > 32767 || $minute < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the minutes (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($second > 32767 || $second < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the seconds (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-
-	print $so pack("va24vvvvvv", 0x7950, $userid, $year, $month, $day, $hour, $minute, $second);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7951) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(32);
-	my(@dat) = unpack("Va24V", $buf);
-	while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) {
-		chop($dat[1]);
-	};
-	if ($dat[0] == -1 || $dat[0] == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement de la validité du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] validity limit changing failed. Account doesn't exist.\n";
-		}
-	} elsif ($dat[2] == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Limite de validité du compte [$dat[1]][id: $dat[0]] inchangée.\n";
-			print "Le compte a une validité illimitée ou\n";
-			print "la modification est impossible avec les ajustements demandés.\n";
-		} else {
-			print "Validity limit of the account [$dat[1]][id: $dat[0]] unchanged.\n";
-			print "The account have an unlimited validity limit or\n";
-			print "the changing is impossible with the proposed adjustments.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Limite de validité du compte [$dat[1]][id: $dat[0]] changée avec succès ".
-			($dat[2] == 0 ? "en [illimité].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2])));
-		} else {
-			print "Validity limit of the account [$dat[1]][id: $dat[0]] successfully changed ".
-			($dat[2] == 0 ? "to [unlimited].\n" : "to be until ".(POSIX::ctime($dat[2])));
-		}
-		# localtime($dat[2]) is also possible to display instead of POSIX::ctime.
-	}
-
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Set the final date of a banishment of an account
-sub bansetaccount() {
-	my($userid, $date, $time) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple>: banset <nom_du_compte> aaaa/mm/jj [hh:mm:ss]\n";
-			print "           banset <nom_du_compte> 0    (0 = dé-bani)\n";
-			print "           ban/banish aaaa/mm/jj hh:mm:ss <nom du compte>\n";
-			print "           unban/unbanish <nom du compte>\n";
-			printf "          Heure par défaut [hh:mm:ss]: 23:59:59\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example>: banset <account_name> yyyy/mm/dd [hh:mm:ss]\n";
-			print "           banset <account_name> 0   (0 = un-banished)\n";
-			print "           ban/banish yyyy/mm/dd hh:mm:ss <account name>\n";
-			print "           unban/unbanish <account name>\n";
-			printf "          Default time [hh:mm:ss]: 23:59:59\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	my($year, $month, $day) = split(/[.\-\/]/, $date);
-	my($hour, $minute, $second) = split(/:/, $time);
-	if ($time eq "") {
-		$hour = 23;
-		$minute = 59;
-		$second = 59;
-	}
-	my($timestamp);
-	if ($year eq "" ||
-	    ($year != 0 && ($month eq "" || $day eq "" || $hour eq "" || $minute eq "" || $second eq ""))) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n";
-		} else {
-			print "Please input 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n";
-		}
-		return 102;
-	}
-	if ($year == 0) {
-		$timestamp = 0;
-	} else {
-		if ($year < 70) {
-			$year = $year + 100;
-		}
-		if ($year >= 1900) {
-			$year = $year - 1900;
-		}
-		if ($month < 1 || $month > 12) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un mois correct svp (entre 1 et 12).\n";
-			} else {
-				print "Please give a correct value for the month (from 1 to 12).\n";
-			}
-			return 102;
-		}
-		$month = $month - 1;
-		if ($day < 1 || $day > 31) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un jour correct svp (entre 1 et 31).\n";
-			} else {
-				print "Please give a correct value for the day (from 1 to 31).\n";
-			}
-			return 102;
-		}
-		if ((($month == 3 || $month == 5 || $month == 8 || $month == 10) && $day > 30) ||
-		    ($month == 1 && $day > 29)) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez un jour correct en fonction du mois svp.\n";
-			} else {
-				print "Please give a correct value for a day of this month.\n";
-			}
-			return 102;
-		}
-		if ($hour < 0 || $hour > 23) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez une heure correcte svp (entre 0 et 23).\n";
-			} else {
-				print "Please give a correct value for the hour (from 0 to 23).\n";
-			}
-			return 102;
-		}
-		if ($minute < 0 || $minute > 59) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez des minutes correctes svp (entre 0 et 59).\n";
-			} else {
-				print "Please give a correct value for the minutes (from 0 to 59).\n";
-			}
-			return 102;
-		}
-		if ($second < 0 || $second > 59) {
-			if ($defaultlanguage eq "F") {
-				print "Entrez des secondes correctes svp (entre 0 et 59).\n";
-			} else {
-				print "Please give a correct value for the seconds (from 0 to 59).\n";
-			}
-			return 102;
-		}
-		$timestamp = POSIX::mktime($second, $minute, $hour, $day, $month, $year, 0, 0, -1); # -1: no winter/summer time modification
-		if ($timestamp == undef) {
-			if ($defaultlanguage eq "F") {
-				print "Date incorrecte.\n";
-				print "Ajoutez 0 ou une date et une heure svp (format: 0 ou aaaa/mm/jj hh:mm:ss).\n";
-			} else {
-				print "Invalid date.\n";
-				print "Please add 0 or a date and a time (format: 0 or yyyy/mm/dd hh:mm:ss).\n";
-			}
-			return 102;
-		}
-	}
-
-	print $so pack("va24V", 0x794a, $userid, $timestamp);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x794b) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(32);
-	my(@dat) = unpack("Va24V", $buf);
-	while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) {
-		chop($dat[1]);
-	};
-	if ($dat[0] != -1 && $dat[0] != 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Date finale de banissement du compte [$dat[1]][id: $dat[0]] changée avec succès ".
-			($dat[2] == 0 ? "en [dé-bannie].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2])));
-		} else {
-			print "Final date of banishment of the account [$dat[1]][id: $dat[0]] successfully changed ".
-			($dat[2] == 0 ? "to [unbanished].\n" : "to be until ".(POSIX::ctime($dat[2])));
-		}
-		# localtime($dat[2]) is also possible to display instead of POSIX::ctime.
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement de la date finale de banissement du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] final date of banishment changing failed. Account doesn't exist.\n";
-		}
-	}
-
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Add/substract time to the final date of a banishment of an account
-sub banaddaccount() {
-	my($userid, $modif) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "  <exemple> banadd nomtest +1m-2mn1s-6y\n";
-			print "            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n";
-			print "            et 6 ans dans le même temps.\n";
-		} else {
-			print "Please input an account name.\n";
-			print "  <example> banadd testname +1m-2mn1s-6y\n";
-			print "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			print "            and 6 years at the same time.\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	my($year, $month, $day) = (0, 0 ,0);
-	my($hour, $minute, $second) = (0, 0 ,0);
-
-	$modif = lc($modif);
-	while (length($modif) > 0) {
-		my($value) = int($modif);
-		if ($value == 0) {
-			$modif = substr($modif, 1);
-		} else {
-			if (substr($modif, 0, 1) =~ /[\-\+]/) {
-				$modif = substr($modif, 1);
-			}
-			while (length($modif) > 0 && substr($modif, 0, 1) =~ /[0-9]/) {
-				$modif = substr($modif, 1);
-			}
-			if (index($modif, "s") == 0) {
-				$second = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "mn") == 0) {
-				$minute = $value;
-				$modif = substr($modif, 2);
-			} elsif (index($modif, "h") == 0) {
-				$hour = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "d") == 0 || index($modif, "j") == 0) {
-				$day = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "m") == 0) {
-				$month = $value;
-				$modif = substr($modif, 1);
-			} elsif (index($modif, "y") == 0 || index($modif, "a") == 0) {
-				$year = $value;
-				$modif = substr($modif, 1);
-			} else {
-				$modif = substr($modif, 1);
-			}
-		}
-	}
-
-	if ($defaultlanguage eq "F") {
-		print " année:   $year\n";
-		print " mois:    $month\n";
-		print " jour:    $day\n";
-		print " heure:   $hour\n";
-		print " minute:  $minute\n";
-		print " seconde: $second\n";
-	} else {
-		print " year:   $year\n";
-		print " month:  $month\n";
-		print " day:    $day\n";
-		print " hour:   $hour\n";
-		print " minute: $minute\n";
-		print " second: $second\n";
-	}
-
-	if ($year == 0 && $month == 0 && $day == 0 && $hour == 0 && $minute == 0 && $second == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Vous devez entrer un ajustement avec cette commande, svp:\n";
-			print "  Valeur d'ajustement (-1, 1, +1, etc...)\n";
-			print "  Element modifié:\n";
-			print "    a ou y: année\n";
-			print "    m:      mois\n";
-			print "    j ou d: jour\n";
-			print "    h:      heure\n";
-			print "    mn:     minute\n";
-			print "    s:      seconde\n";
-			print "  <exemple> banadd nomtest +1m-2mn1s-6y\n";
-			print "            Cette exemple ajoute 1 mois et 1 seconde, et soustrait 2 minutes\n";
-			print "            et 6 ans dans le même temps.\n";
-		} else {
-			print "Please give an adjustment with this command:\n";
-			print "  Adjustment value (-1, 1, +1, etc...)\n";
-			print "  Modified element:\n";
-			print "    a or y: year\n";
-			print "    m: month\n";
-			print "    j or d: day\n";
-			print "    h: hour\n";
-			print "    mn: minute\n";
-			print "    s: second\n";
-			print "  <example> banadd testname +1m-2mn1s-6y\n";
-			print "            this example adds 1 month and 1 second, and substracts 2 minutes\n";
-			print "            and 6 years at the same time.\n";
-		}
-		return 137;
-	}
-	if ($year > 127 || $year < -127) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement d'années correct (de -127 à 127), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the years (from -127 to 127).\n";
-		}
-		return 137;
-	}
-	if ($month > 255 || $month < -255) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de mois correct (de -255 à 255), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the months (from -255 to 255).\n";
-		}
-		return 137;
-	}
-	if ($day > 32767 || $day < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de jours correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the days (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($hour > 32767 || $hour < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement d'heures correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the hours (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($minute > 32767 || $minute < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de minutes correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the minutes (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-	if ($second > 32767 || $second < -32767) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un ajustement de secondes correct (de -32767 à 32767), svp.\n";
-		} else {
-			print "Please give a correct adjustment for the seconds (from -32767 to 32767).\n";
-		}
-		return 137;
-	}
-
-	print $so pack("va24vvvvvv", 0x794c, $userid, $year, $month, $day, $hour, $minute, $second);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x794d) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(32);
-	my(@dat) = unpack("Va24V", $buf);
-	while (length($dat[1]) > 0 && substr($dat[1], length($dat[1])-1, 1) eq chr(0)) {
-		chop($dat[1]);
-	};
-	if ($dat[0] == -1 || $dat[0] == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Echec du changement de la date finale de banissement du compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Account [$userid] final date of banishment changing failed. Account doesn't exist.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Date finale de banissement du compte [$dat[1]][id: $dat[0]] changée avec succès ".
-			($dat[2] == 0 ? "en [dé-bannie].\n" : "pour être jusqu'au ".(POSIX::ctime($dat[2])));
-		} else {
-			print "Final date of banishment of the account [$dat[1]][id: $dat[0]] successfully changed ".
-			($dat[2] == 0 ? "to [unbanished].\n" : "to be until ".(POSIX::ctime($dat[2])));
-		}
-		# localtime($dat[2]) is also possible to display instead of POSIX::ctime.
-	}
-
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Request to displaying information about an account (by its name)
-sub whoaccount() {
-	my($userid) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> who nomtest\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> who testname\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-
-	print $so pack("va24", 0x7952, $userid);
-	$so->flush();
-
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7953) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 122;
-	}
-	my($id2, $GM_level, $name, $sex, $count, $status, $error_message, $last_login, $last_ip, $email, $validite, $ban_date, $memo_size) = unpack("VCa24cVVa20a24a16a40VVv", readso(148));
-	my($memo) = "";
-	if ($memo_size > 0) {
-		$memo = unpack("a".$memo_size, readso($memo_size));
-	}
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	while (length($error_message) > 0 && substr($error_message, length($error_message)-1, 1) eq chr(0)) {
-		chop($error_message);
-	};
-	while (length($last_login) > 0 && substr($last_login, length($last_login)-1, 1) eq chr(0)) {
-		chop($last_login);
-	};
-	while (length($last_ip) > 0 && substr($last_ip, length($last_ip)-1, 1) eq chr(0)) {
-		chop($last_ip);
-	};
-	while (length($email) > 0 && substr($email, length($email)-1, 1) eq chr(0)) {
-		chop($email);
-	};
-	while (length($memo) > 0 && substr($memo, length($memo)-1, 1) eq chr(0)) {
-		chop($memo);
-	};
-
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Impossible de trouver le compte [$userid]. Le compte n'existe pas.\n";
-		} else {
-			print "Unabled to find the account [$userid]. Account doesn't exist.\n";
-		}
-		return 123;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Le compte [$userid] a les caractéristiques suivantes:\n";
-		} else {
-			print "The account [$userid] is set with:\n";
-		}
-		if ($GM_level == 0) {
-			print " Id:     $id2 (non-GM)\n";
-		} else {
-			if ($defaultlanguage eq "F") {
-				print " Id:     $id2 (GM niveau $GM_level)\n";
-			} else {
-				print " Id:     $id2 (GM level $GM_level)\n";
-			}
-		}
-		if ($defaultlanguage eq "F") {
-			print " Nom:    '$name'\n";
-			print " Sexe:   ".("Femme", "Male", "Serveur")[$sex]."\n";
-		} else {
-			print " Name:   '$name'\n";
-			print " Sex:    ".("Female", "Male", "Server")[$sex]."\n";
-		}
-		print " E-mail: $email\n";
-		if ($status == 7) {
-			print " Statut: 7 [You are Prohibited to log in until $error_message]\n";
-		} else {
-			print " Statut: $status [".(
-			      ($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"),
-			      "Unregistered ID",
-			      "Incorrect Password",
-			      "This ID is expired",
-			      "Rejected from Server",
-			      "You have been blocked by the GM Team",
-			      "Your Game's EXE file is not the latest version",
-			      "You are Prohibited to log in until %s",
-			      "Server is jammed due to over populated",
-			      "No MSG",
-			      "This ID is totally erased")[$status == 100 ? 10 : $status]."]\n";
-		}
-		if ($defaultlanguage eq "F") {
-			print " Banissement: ".($ban_date == 0 ? "non banni.\n" : "jusqu'au ".(POSIX::ctime($ban_date)));
-			print " Compteur: $count connexion".("s", "")[$count > 1 ? 0 : 1]."\n";
-			print " Dernière connexion le: $last_login (ip: $last_ip)\n";
-			print " Limite de validité: ".($validite == 0 ? "illimité.\n" : "jusqu'au ".(POSIX::ctime($validite)));
-		} else {
-			print " Banishment: ".($ban_date == 0 ? "not banished.\n" : "until ".(POSIX::ctime($ban_date)));
-			print " Count: $count connection".("s", "")[$count > 1 ? 0 : 1]."\n";
-			print " Last connection at: $last_login (ip: $last_ip)\n";
-			print " Validity limit: ".($validite == 0 ? "unlimited.\n" : "until ".(POSIX::ctime($validite)));
-		}
-		print " Memo:   '$memo'\n";
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Request to displaying information about an account (by its id)
-sub infoaccount() {
-	my($id) = @_;
-	if ($id < 0) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un id ayant une valeur positive svp.\n";
-		} else {
-			print "Please input a positive value for the id.\n";
-		}
-		return 136;
-	}
-
-	print $so pack("vV", 0x7954, $id);
-	$so->flush();
-
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x7953) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 122;
-	}
-	my($id2, $GM_level, $name, $sex, $count, $status, $error_message, $last_login, $last_ip, $email, $validite, $ban_date, $memo_size) = unpack("VCa24cVVa20a24a16a40VVv", readso(148));
-	my($memo) = "";
-	if ($memo_size > 0) {
-		$memo = unpack("a".$memo_size, readso($memo_size));
-	}
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	while (length($error_message) > 0 && substr($error_message, length($error_message)-1, 1) eq chr(0)) {
-		chop($error_message);
-	};
-	while (length($last_login) > 0 && substr($last_login, length($last_login)-1, 1) eq chr(0)) {
-		chop($last_login);
-	};
-	while (length($last_ip) > 0 && substr($last_ip, length($last_ip)-1, 1) eq chr(0)) {
-		chop($last_ip);
-	};
-	while (length($email) > 0 && substr($email, length($email)-1, 1) eq chr(0)) {
-		chop($email);
-	};
-	while (length($memo) > 0 && substr($memo, length($memo)-1, 1) eq chr(0)) {
-		chop($memo);
-	};
-
-	if (length($name) == 0 || $name eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Impossible de trouver le nom du compte [id: $id2]. Le compte n'existe pas.\n";
-		} else {
-			print "Unabled to find the account [id: $id2] name. Account doesn't exist.\n";
-		}
-		return 123;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Le compte [id: $id2] a les caractéristiques suivantes:\n";
-		} else {
-			print "The account [id: $id2] is set with:\n";
-		}
-		if ($GM_level == 0) {
-			print " Id:     $id2 (non-GM)\n";
-		} else {
-			if ($defaultlanguage eq "F") {
-				print " Id:     $id2 (GM niveau $GM_level)\n";
-			} else {
-				print " Id:     $id2 (GM level $GM_level)\n";
-			}
-		}
-		if ($defaultlanguage eq "F") {
-			print " Nom:    '$name'\n";
-			print " Sexe:   ".("Femme", "Male", "Serveur")[$sex]."\n";
-		} else {
-			print " Name:   '$name'\n";
-			print " Sex:    ".("Female", "Male", "Server")[$sex]."\n";
-		}
-		print " E-mail: $email\n";
-		if ($status == 7) {
-			print " Statut: 7 [You are Prohibited to log in until $error_message]\n";
-		} else {
-			print " Statut: $status [".(
-			      ($defaultlanguage eq "F" ? "Compte Ok" : "Account OK"),
-			      "Unregistered ID",
-			      "Incorrect Password",
-			      "This ID is expired",
-			      "Rejected from Server",
-			      "You have been blocked by the GM Team",
-			      "Your Game's EXE file is not the latest version",
-			      "You are Prohibited to log in until %s",
-			      "Server is jammed due to over populated",
-			      "No MSG",
-			      "This ID is totally erased")[$status == 100 ? 10 : $status]."]\n";
-		}
-		if ($defaultlanguage eq "F") {
-			print " Banissement: ".($ban_date == 0 ? "non banni.\n" : "jusqu'au ".(POSIX::ctime($ban_date)));
-			print " Compteur: $count connexion".("s", "")[$count > 1 ? 0 : 1]."\n";
-			print " Dernière connexion le: $last_login (ip: $last_ip)\n";
-			print " Limite de validité: ".($validite == 0 ? "illimité.\n" : "jusqu'au ".(POSIX::ctime($validite)));
-		} else {
-			print " Banishment: ".($ban_date == 0 ? "not banished.\n" : "until ".(POSIX::ctime($ban_date)));
-			print " Count: $count connection".("s", "")[$count > 1 ? 0 : 1]."\n";
-			print " Last connection at: $last_login (ip: $last_ip)\n";
-			print " Validity limit: ".($validite == 0 ? "unlimited.\n" : "until ".(POSIX::ctime($validite)));
-		}
-		print " Memo:   '$memo'\n";
-	}
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Check the validity of a password
-# (Note: never send back a password with login-server!! security of passwords)
-sub checkaccount() {
-	my($userid, $passwd) = @_;
-	if ($userid eq "") {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un nom de compte svp.\n";
-			print "<exemple> check testname motdepasse\n";
-		} else {
-			print "Please input an account name.\n";
-			print "<example> check testname password\n";
-		}
-		return 136;
-	}
-	if (verify_accountname($userid) == 0) {
-		return 102;
-	}
-	if ($passwd eq "") {
-		return 134 if (($passwd = typepasswd()) eq "");
-	}
-	if (verify_password($passwd) == 0) {
-		return 131;
-	}
-	print $so pack("va24a24", 0x793a, $userid,$passwd);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x793b) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 132;
-	}
-	$buf = readso(28);
-	my($id2, $name) = unpack("Va24", $buf);
-	while (length($name) > 0 && substr($name, length($name)-1, 1) eq chr(0)) {
-		chop($name);
-	};
-	if ($id2 == -1 || $id2 == 4294967295) {
-		if ($defaultlanguage eq "F") {
-			print "Le compte [$userid] n'existe pas ou le mot de passe est incorrect.\n";
-		} else {
-			print "The account [$userid] doesn't exist or the password is incorrect.\n";
-		}
-		return 133;
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Le mot de passe donné correspond bien au compte [$name][id: $id2].\n";
-		} else {
-			print "The proposed password is correct for the account [$name][id: $id2].\n";
-		}
-	}
-	return 130;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Request to login-server to reload GM configuration file
-sub reloadGM() {
-	print $so pack("v", 0x7955);
-	$so->flush();
-	if ($defaultlanguage eq "F") {
-		print "Demande de recharger le fichier de configuration des GM envoyée.\n";
-		print "Vérifiez les comptes GM actuels (après rechargement):\n";
-	} else {
-		print "Request to reload the GM configuration file sended.\n";
-		print "Check the actual GM accounts (after reloading):\n";
-	}
-	&listaccount(0, 0, 1); # 1: to list only GM
-	return 180;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Send a broadcast message
-sub sendbroadcast() {
-	my($type, $message) = @_;
-	if ($message eq "" || length($message) == 0) {
-		if ($defaultlanguage eq "F") {
-			print "Entrez un message svp.\n";
-			if ($type == 0) {
-				print "<exemple> kami un message\n";
-			} else {
-				print "<exemple> kamib un message\n";
-			}
-		} else {
-			print "Please input a message.\n";
-			if ($type == 0) {
-				print "<example> kami a message\n";
-			} else {
-				print "<example> kamib a message\n";
-			}
-		}
-		return 136;
-	}
-
-	print $so pack("vvVa".length($message), 0x794e, $type, length($message), $message);
-	$so->flush();
-	$buf = readso(2);
-	if (unpack("v", $buf) != 0x794f) {
-		if ($defaultlanguage eq "F") {
-			print "Problème de connexion au serveur (réponse incorrecte).\n";
-		} else {
-			print "Connection error to the server (incorrect answer).\n";
-		}
-		return 152;
-	}
-	$buf = readso(2);
-	my($answer) = unpack("v", $buf);
-	if ($answer == -1 || $answer == 65535) {
-		if ($defaultlanguage eq "F") {
-			print "Echec de l'envoi du message. Aucun server de char en ligne.\n";
-		} else {
-			print "Message sending failed. No online char-server.\n";
-		}
-	} else {
-		if ($defaultlanguage eq "F") {
-			print "Message transmis au server de logins avec succès.\n";
-		} else {
-			print "Message successfully sended to login-server.\n";
-		}
-	}
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Change language of displaying
-sub changelanguage() {
-	my($language) = @_;
-	if ($language eq "" || length($language) == 0) {
-		if ($defaultlanguage == 'F') {
-			printf("Entrez une langue svp.\n");
-			printf("<exemple> language english\n");
-			printf("          language français\n");
-		} else {
-			printf("Please input a language.\n");
-			printf("<example> language english\n");
-			printf("          language français\n");
-		}
-		return 136;
-	}
-
-	$language = uc(substr($language, 0, 1));
-	if ($language =~ /^[EF]$/) {
-		$defaultlanguage = $language;
-		if ($defaultlanguage == 'F') {
-			printf("Changement de la langue d'affichage en Français.\n");
-		} else {
-			printf("Displaying language changed to English.\n");
-		}
-	} else {
-		if ($defaultlanguage == 'F') {
-			printf("Langue non paramétrée (langues possibles: 'Français' ou 'English').\n");
-		} else {
-			printf("Undefined language (possible languages: Français or English).\n");
-		}
-	}
-
-	return 0;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: sending 'end of connection' packet
-sub quit() {
-	print $so pack("v", 0x7532);
-	$so->flush();
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Get datas from the socket
-sub readso() {
-	my($len) = shift;
-	my($buf);
-	if (read($so, $buf, $len) < $len) {
-		if ($defaultlanguage eq "F") {
-			print "Erreur de lecture sur la Socket.\n";
-		} else {
-			print "Socket read error.\n";
-		}
-		exit(3);
-	}
-	return $buf;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Input of a password
-sub typepasswd {
-	my($passwd1, $passwd2);
-	cbreak();
-	if ($defaultlanguage eq "F") {
-		print "Entrez le mot de passe > "; $passwd1 = <STDIN>; chomp($passwd1); print "\n";
-		print "Ré-entrez le mot de passe > "; $passwd2 = <STDIN>; chomp($passwd2); print "\n";
-	} else {
-		print "Type the password > "; $passwd1 = <STDIN>; chomp($passwd1); print "\n";
-		print "Verify the password > "; $passwd2 = <STDIN>; chomp($passwd2); print "\n";
-	}
-	cooked();
-	if ($passwd1 ne $passwd2) {
-		if ($defaultlanguage eq "F") {
-			print "Erreur de vérification du mot de passe: Saisissez le même mot de passe svp.\n";
-		} else {
-			print "Password verification failed. Please input same password.\n";
-		}
-		return "";
-	}
-	return $passwd1;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Return ordonal text of a number
-sub makeordinal {
-	my($c) = shift;
-	if ($defaultlanguage eq "F") {
-		if ($c < 1) {
-			return $c;
-		}
-		return $c.("er", "ème")[$c == 1 ? 0 : 1];
-	} else {
-		if ($c % 10 < 4 && $c % 10 != 0 && ($c < 10 || $c > 20)) {
-			return $c.("st","nd","rd")[$c % 10 - 1];
-		}
-		return $c."th";
-	}
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Test of the validity of an account name (return 0 if incorrect, and 1 if ok)
-sub verify_accountname {
-	my($account_name) = @_;       # Get the account_name
-	if ($account_name =~ /[\x00-\x1f]/) { # remove control char
-		my($c) = length($`) + 1;
-		if ($defaultlanguage eq "F") {
-			print "Caractère interdit trouvé dans le nom du compte (".makeordinal($c)." caractère).\n";
-		} else {
-			print "Illegal character found in the account name (".makeordinal($c)." character).\n";
-		}
-		return 0;
-	}
-	if (length($account_name) < 4) {
-		if ($defaultlanguage eq "F") {
-			print "Nom du compte trop court. Entrez un nom de compte de 4-23 caractères.\n";
-		} else {
-			print "Account name is too short. Please input an account name of 4-23 bytes.\n";
-		}
-		return 0;
-	}
-	if (length($account_name) > 23) {
-		if ($defaultlanguage eq "F") {
-			print "Nom du compte trop long. Entrez un nom de compte de 4-23 caractères.\n";
-		} else {
-			print "Account name is too long. Please input an account name of 4-23 bytes.\n";
-		}
-		return 0;
-	}
-	return 1;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Test of the validity of password (return 0 if incorrect, and 1 if ok)
-sub verify_password {
-	my($password) = @_;       # Get the password
-	if ($password =~ /[\x00-\x1f]/) {
-		my($c) = length($`) + 1;
-		if ($defaultlanguage eq "F") {
-			print "Caractère interdit trouvé dans le mot de passe (".makeordinal($c)." caractère).\n";
-		} else {
-			print "Illegal character found in the password (".makeordinal($c)." character).\n";
-		}
-		return 0;
-	}
-	if (length($password) < 4) {
-		if ($defaultlanguage eq "F") {
-			print "Mot de passe trop court. Entrez un mot de passe de 4-23 caractères.\n";
-		} else {
-			print "Password is too short. Please input a password of 4-23 bytes.\n";
-		}
-		return 0;
-	}
-	if (length($password) > 23) {
-		if ($defaultlanguage eq "F") {
-			print "Mot de passe trop long. Entrez un mot de passe de 4-23 caractères.\n";
-		} else {
-			print "Password is too long. Please input a password of 4-23 bytes.\n";
-		}
-		return 0;
-	}
-	return 1;
-}
-
-#--------------------------------------------------------------------------
-
-# Sub-function: Test of the validity of an e-mail (return 0 if incorrect, and 1 if ok)
-sub verify_email {
-	my($email) = @_;       # Get the e-mail
-	# To ignore a '.' before the @ (wanadoo, a provider, do that)
-	$email =~ s/\.\@/\@/;
-	# If the e-mail is void, it's not correct -> return 0
-	if ($email eq '') {
-		return(0);
-	}
-	# If the e-mail have no "@", it's not correct -> return 0
-	if ($email !~ /\@/) {
-		return(0);
-	}
-	# If the e-mail have a ",", a space, a tab or a ";", it's not correct -> return 0
-	if ($email =~ /[\,|\s|\;]/) {
-		return(0)
-	};
-	# IF
-	#    (the e-mail contains 2 "@", or ".." or "@." or starts or finishes by a ".")
-	# OR IF
-	#    (the e-mail doesn't contain "@localhost" AND
-	# - it doesn't contain characters followed by "@" itself followed by letters itself followed by "." and 2 or more letters
-	# - or an IP address)
-	# -> so, it's not good ! (finish !)
-	if ($email =~ /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)|(\.$)/ ||
-		($email !~ /^.+\@localhost$/ &&
-		$email !~ /^.+\@\[?(\w|[-.])+\.[a-zA-Z]{2,3}|[0-9]{1,3}\]?$/)) {
-		return(0); # non-valid email
-	} else {
-		# If not, the e-email address is correct
-		return(1); # valid email
-	}
-}

+ 270 - 270
vcproj-6/char-server_sql.dsp

@@ -1,270 +1,270 @@
-# Microsoft Developer Studio Project File - Name="char_sql" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=char_sql - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "char-server_sql.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "char-server_sql.mak" CFG="char_sql - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "char_sql - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /I "..\src\mysql" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/char_sql/char-server_sql.pch" /YX /Fo"tmp/char_sql/" /Fd"tmp/char_sql/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 wsock32.lib libmysql.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/char_sql/char-server_sql.pdb" /machine:I386 /out:"../char-server_sql.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "char_sql - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "char_sql"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\char_sql\char.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\char.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_auction.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_auction.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_guild.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_guild.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_homun.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_homun.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_mail.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_mail.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_party.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_party.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_pet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_pet.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_storage.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_storage.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_quest.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\int_quest.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\inter.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\inter.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="char_sql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=char_sql - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "char-server_sql.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "char-server_sql.mak" CFG="char_sql - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "char_sql - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /I "..\3rdparty\mysql\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/char_sql/char-server_sql.pch" /YX /Fo"tmp/char_sql/" /Fd"tmp/char_sql/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib libmysql.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/char_sql/char-server_sql.pdb" /machine:I386 /out:"../char-server_sql.exe" /libpath:"..\3rdparty\mysql\lib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "char_sql - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "char_sql"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\char_sql\char.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\char.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_auction.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_auction.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_guild.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_guild.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_homun.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_homun.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_mail.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_mail.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_party.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_party.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_pet.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_pet.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_quest.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_quest.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_storage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\int_storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\inter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char_sql\inter.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 246 - 246
vcproj-6/char-server_txt.dsp

@@ -1,246 +1,246 @@
-# Microsoft Developer Studio Project File - Name="char_txt" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=char_txt - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "char-server_txt.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "char-server_txt.mak" CFG="char_txt - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "char_txt - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "TXT_ONLY" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/char_txt/char-server_txt.pch" /YX /Fo"tmp/char_txt/" /Fd"tmp/char_txt/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 wsock32.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/char-txt/char-server_txt.pdb" /machine:I386 /out:"../char-server_txt.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "char_txt - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "char"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\char\char.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\char.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_guild.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_guild.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_homun.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_homun.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_party.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_party.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_pet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_pet.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_status.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_status.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_storage.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\int_storage.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\inter.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char\inter.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="char_txt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=char_txt - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "char-server_txt.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "char-server_txt.mak" CFG="char_txt - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "char_txt - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "TXT_ONLY" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/char_txt/char-server_txt.pch" /YX /Fo"tmp/char_txt/" /Fd"tmp/char_txt/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 wsock32.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/char-txt/char-server_txt.pdb" /machine:I386 /out:"../char-server_txt.exe"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "char_txt - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "char"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\char\char.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\char.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_guild.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_guild.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_homun.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_homun.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_party.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_party.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_pet.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_pet.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_status.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_status.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_storage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\int_storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\inter.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\char\inter.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 238 - 210
vcproj-6/login-server_sql.dsp

@@ -1,210 +1,238 @@
-# Microsoft Developer Studio Project File - Name="login_sql" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=login_sql - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "login-server_sql.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "login-server_sql.mak" CFG="login_sql - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "login_sql - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /I "..\src\mysql" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D PACKETVER=6 /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/login_sql/login-server_sql.pch" /YX /Fo"tmp/login_sql/" /Fd"tmp/login_sql/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 WSOCK32.lib libmysql.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/login_sql/login-server_sql.pdb" /machine:I386 /out:"../login-server_sql.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "login_sql - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\md5calc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\md5calc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\svnversion.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "login_sql"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\login_sql\login.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\login_sql\login.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="login_sql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=login_sql - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "login-server_sql.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "login-server_sql.mak" CFG="login_sql - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "login_sql - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /I "..\3rdparty\mysql\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D PACKETVER=6 /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /D "WITH_SQL" /Fp"tmp/login_sql/login-server_sql.pch" /YX /Fo"tmp/login_sql/" /Fd"tmp/login_sql/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 WSOCK32.lib libmysql.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/login_sql/login-server_sql.pdb" /machine:I386 /out:"../login-server_sql.exe" /libpath:"..\3rdparty\mysql\lib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "login_sql - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\md5calc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\md5calc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\svnversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "login_sql"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\login\account.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\account_sql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\admin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\ipban.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\ipban_sql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\login.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\login.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\loginlog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\loginlog_sql.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 230 - 202
vcproj-6/login-server_txt.dsp

@@ -1,202 +1,230 @@
-# Microsoft Developer Studio Project File - Name="login_txt" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=login_txt - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "login-server_txt.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "login-server_txt.mak" CFG="login_txt - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "login_txt - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D "TXT_ONLY" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/login_txt/login-server_txt.pch" /YX /Fo"tmp/login_txt/" /Fd"tmp/login_txt/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 WSOCK32.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/login_txt/login-server_txt.pdb" /machine:I386 /out:"../login-server_txt.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "login_txt - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\md5calc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\svnversion.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "login"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\login\admin.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\login\login.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\login\login.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="login_txt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=login_txt - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "login-server_txt.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "login-server_txt.mak" CFG="login_txt - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "login_txt - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D "__WIN32" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /D "WITH_TXT" /D "ACCOUNTDB_ENGINE_0=rj" /Fp"tmp/login_txt/login-server_txt.pch" /YX /Fo"tmp/login_txt/" /Fd"tmp/login_txt/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 WSOCK32.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/login_txt/login-server_txt.pdb" /machine:I386 /out:"../login-server_txt.exe"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "login_txt - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\md5calc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\svnversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "login"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\login\account.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\account_rj.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\account_txt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\admin.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\ipban.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\ipban_txt.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\login.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\login.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\loginlog.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\login\loginlog_txt.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 434 - 450
vcproj-6/map-server_sql.dsp

@@ -1,450 +1,434 @@
-# Microsoft Developer Studio Project File - Name="map_sql" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=map_sql - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "map-server_sql.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "map-server_sql.mak" CFG="map_sql - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "map_sql - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /I "..\src\zlib" /I "..\src\mysql" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "__WIN32" /D "PCRE_SUPPORT" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/map_sql/map-server_sql.pch" /YX /Fo"tmp/map_sql/" /Fd"tmp/map_sql/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 WSOCK32.lib libmysql.lib pcre.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/map_sql/map-server_sql.pdb" /machine:I386 /out:"../map-server_sql.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "map_sql - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\grfio.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\grfio.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\sql.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\svnversion.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "map"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\map\atcommand.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\atcommand.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\battle.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\battle.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\charcommand.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\charcommand.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chat.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chat.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chrif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chrif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\clif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\clif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\date.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\date.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\guild.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\guild.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\intif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\intif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\irc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\irc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\itemdb.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\itemdb.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\log.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\log.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mail.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mail.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\map.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\map.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mercenary.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mercenary.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mob.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mob.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc_chat.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\party.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\party.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\path.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\path.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pcre.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pet.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\script.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\script.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\skill.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\skill.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\status.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\status.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\storage.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\storage.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\trade.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\trade.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\unit.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\vending.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\vending.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\quest.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\quest.h
-# End Source File
-# End Group
-# Begin Group "zlib"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\zlib\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\zlib\zlib.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="map_sql" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=map_sql - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "map-server_sql.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "map-server_sql.mak" CFG="map_sql - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "map_sql - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /I "..\3rdparty\mysql\include" /I "..\3rdparty\zlib\include" /I "..\3rdparty\pcre\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "__WIN32" /D "PCRE_SUPPORT" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/map_sql/map-server_sql.pch" /YX /Fo"tmp/map_sql/" /Fd"tmp/map_sql/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 WSOCK32.lib libmysql.lib zdll.lib pcre.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/map_sql/map-server_sql.pdb" /machine:I386 /out:"../map-server_sql.exe" /libpath:"..\3rdparty\mysql\lib" /libpath:"..\3rdparty\zlib\lib" /libpath:"..\3rdparty\pcre\lib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "map_sql - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\grfio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\grfio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\sql.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\svnversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "map"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\map\atcommand.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\atcommand.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\battle.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\battle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\charcommand.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\charcommand.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chrif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chrif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\clif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\clif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\date.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\date.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\guild.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\guild.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\intif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\intif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\irc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\irc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\itemdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\itemdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mail.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mail.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\map.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mercenary.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mercenary.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mob.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mob.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc_chat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\party.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\party.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\path.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\path.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pet.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pet.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\quest.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\quest.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\script.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\script.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\skill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\skill.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\status.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\status.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\storage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\trade.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\trade.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\unit.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\vending.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\vending.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 430 - 446
vcproj-6/map-server_txt.dsp

@@ -1,446 +1,430 @@
-# Microsoft Developer Studio Project File - Name="map_txt" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Console Application" 0x0103
-
-CFG=map_txt - Win32 Release
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE 
-!MESSAGE NMAKE /f "map-server_txt.mak".
-!MESSAGE 
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE 
-!MESSAGE NMAKE /f "map-server_txt.mak" CFG="map_txt - Win32 Release"
-!MESSAGE 
-!MESSAGE Possible choices for configuration are:
-!MESSAGE 
-!MESSAGE "map_txt - Win32 Release" (based on "Win32 (x86) Console Application")
-!MESSAGE 
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "Release"
-# PROP BASE Intermediate_Dir "Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "Release"
-# PROP Intermediate_Dir "Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
-# ADD CPP /nologo /W2 /GX /O2 /I "..\src\common" /I "..\src\zlib" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "TXT_ONLY" /D "__WIN32" /D "PCRE_SUPPORT" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/map_txt/map-server_txt.pch" /YX /Fo"tmp/map_txt/" /Fd"tmp/map_txt/" /FD /c
-# ADD BASE RSC /l 0x409
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
-# ADD LINK32 WSOCK32.lib pcre.lib zdll.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/map_txt/map-server_txt.pdb" /machine:I386 /out:"../map-server_txt.exe" /libpath:"../lib"
-# SUBTRACT LINK32 /pdb:none
-# Begin Target
-
-# Name "map_txt - Win32 Release"
-# Begin Group "common"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\common\cbasetypes.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\core.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\db.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\ers.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\grfio.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\grfio.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\lock.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\malloc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mapindex.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\mmo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\nullpo.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugin.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\plugins.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\showmsg.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\socket.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\strlib.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\svnversion.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\timer.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\utils.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\common\version.h
-# End Source File
-# End Group
-# Begin Group "map"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\map\atcommand.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\battle.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\charcommand.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chat.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chrif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\clif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\date.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\guild.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\intif.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\irc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\itemdb.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\log.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mail.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\map.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mercenary.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mob.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc_chat.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\party.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\path.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pc.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pet.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\script.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\skill.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\status.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\storage.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\trade.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\unit.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\vending.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\atcommand.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\battle.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\charcommand.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chat.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\chrif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\clif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\date.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\guild.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\intif.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\irc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\itemdb.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\log.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mail.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\map.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mercenary.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\mob.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\npc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\party.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\path.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pc.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pcre.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\pet.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\script.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\skill.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\status.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\storage.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\trade.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\unit.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\vending.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\quest.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\map\quest.h
-# End Source File
-# End Group
-# Begin Group "zlib"
-
-# PROP Default_Filter ""
-# Begin Source File
-
-SOURCE=..\src\zlib\zconf.h
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\zlib\zlib.h
-# End Source File
-# End Group
-# End Target
-# End Project
+# Microsoft Developer Studio Project File - Name="map_txt" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=map_txt - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "map-server_txt.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "map-server_txt.mak" CFG="map_txt - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "map_txt - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W2 /GX /O2 /I "..\3rdparty\zlib\include" /I "..\3rdparty\pcre\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_WIN32" /D "TXT_ONLY" /D "__WIN32" /D "PCRE_SUPPORT" /D FD_SETSIZE=4096 /D "DB_MANUAL_CAST_TO_UNION" /Fp"tmp/map_txt/map-server_txt.pch" /YX /Fo"tmp/map_txt/" /Fd"tmp/map_txt/" /FD /c
+# ADD BASE RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 WSOCK32.lib zdll.lib pcre.lib ws2_32.lib /nologo /subsystem:console /pdb:"tmp/map_txt/map-server_txt.pdb" /machine:I386 /out:"../map-server_txt.exe" /libpath:"..\3rdparty\zlib\lib" /libpath:"..\3rdparty\pcre\lib"
+# SUBTRACT LINK32 /pdb:none
+# Begin Target
+
+# Name "map_txt - Win32 Release"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\common\cbasetypes.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\core.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\db.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\ers.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\grfio.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\grfio.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\lock.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\malloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mapindex.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\mmo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\nullpo.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugin.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\plugins.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\showmsg.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\socket.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\strlib.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\svnversion.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\timer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\utils.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\common\version.h
+# End Source File
+# End Group
+# Begin Group "map"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\src\map\atcommand.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\battle.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\charcommand.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chrif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\clif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\date.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\guild.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\intif.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\irc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\itemdb.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\log.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mail.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\map.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mercenary.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mob.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc_chat.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\party.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\path.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pc.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pet.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\quest.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\script.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\skill.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\status.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\storage.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\trade.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\unit.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\vending.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\atcommand.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\battle.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\charcommand.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\chrif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\clif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\date.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\guild.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\intif.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\irc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\itemdb.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\log.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mail.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\map.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mercenary.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\mob.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\npc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\party.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\path.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\pet.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\quest.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\script.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\skill.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\status.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\storage.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\trade.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\unit.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\src\map\vending.h
+# End Source File
+# End Group
+# End Target
+# End Project

+ 10 - 10
vcproj-7.1/char-server_sql.vcproj

@@ -20,7 +20,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
@@ -39,10 +39,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib"
 				OutputFile="$(OutDir)\char-server_sql.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\$(ProjectName).pdb"
@@ -88,7 +88,7 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
@@ -102,10 +102,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib"
 				OutputFile="$(OutDir)\char-server_sql.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				IgnoreDefaultLibraryNames=""
 				GenerateDebugInformation="TRUE"
@@ -186,16 +186,16 @@
 				RelativePath="..\src\char_sql\int_pet.h">
 			</File>
 			<File
-				RelativePath="..\src\char_sql\int_storage.c">
+				RelativePath="..\src\char_sql\int_quest.c">
 			</File>
 			<File
-				RelativePath="..\src\char_sql\int_storage.h">
+				RelativePath="..\src\char_sql\int_quest.h">
 			</File>
 			<File
-				RelativePath="..\src\char_sql\int_quest.c">
+				RelativePath="..\src\char_sql\int_storage.c">
 			</File>
 			<File
-				RelativePath="..\src\char_sql\int_quest.h">
+				RelativePath="..\src\char_sql\int_storage.h">
 			</File>
 			<File
 				RelativePath="..\src\char_sql\inter.c">

+ 6 - 6
vcproj-7.1/char-server_txt.vcproj

@@ -20,7 +20,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
+				AdditionalIncludeDirectories=""
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
@@ -39,10 +39,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib"
 				OutputFile="$(OutDir)\char-server.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories=""
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\char-server.pdb"
@@ -88,7 +88,7 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
+				AdditionalIncludeDirectories=""
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
@@ -102,10 +102,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib"
 				OutputFile="$(OutDir)\char-server.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories=""
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\char-server.pdb"

+ 31 - 10
vcproj-7.1/login-server_sql.vcproj

@@ -19,8 +19,8 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION;WITH_SQL"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
 				ExceptionHandling="FALSE"
@@ -38,10 +38,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib"
 				OutputFile="$(OutDir)\login-server_sql.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\$(ProjectName).pdb"
@@ -87,8 +87,8 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION;WITH_SQL"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
 				DefaultCharIsUnsigned="FALSE"
@@ -103,10 +103,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib"
 				OutputFile="$(OutDir)\login-server_sql.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				IgnoreDefaultLibraryNames=""
 				GenerateDebugInformation="TRUE"
@@ -145,10 +145,31 @@
 			Name="login_sql"
 			Filter="">
 			<File
-				RelativePath="..\src\login_sql\login.c">
+				RelativePath="..\src\login\account.h">
 			</File>
 			<File
-				RelativePath="..\src\login_sql\login.h">
+				RelativePath="..\src\login\account_sql.c">
+			</File>
+			<File
+				RelativePath="..\src\login\admin.c">
+			</File>
+			<File
+				RelativePath="..\src\login\ipban.h">
+			</File>
+			<File
+				RelativePath="..\src\login\ipban_sql.c">
+			</File>
+			<File
+				RelativePath="..\src\login\login.c">
+			</File>
+			<File
+				RelativePath="..\src\login\login.h">
+			</File>
+			<File
+				RelativePath="..\src\login\loginlog.h">
+			</File>
+			<File
+				RelativePath="..\src\login\loginlog_sql.c">
 			</File>
 		</Filter>
 		<Filter

+ 27 - 8
vcproj-7.1/login-server_txt.vcproj

@@ -19,8 +19,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION;WITH_TXT;ACCOUNTDB_ENGINE_0=rj"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
 				ExceptionHandling="FALSE"
@@ -43,11 +42,11 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib"
 				ShowProgress="0"
 				OutputFile="$(OutDir)\login-server.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories=""
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\login-server.pdb"
@@ -93,8 +92,7 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
-				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
+				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION;WITH_TXT;ACCOUNTDB_ENGINE_0=rj"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
 				DefaultCharIsUnsigned="FALSE"
@@ -107,10 +105,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib"
 				OutputFile="$(OutDir)\login-server.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories=""
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\login-server.pdb"
@@ -147,15 +145,36 @@
 		<Filter
 			Name="login_txt"
 			Filter="">
+			<File
+				RelativePath="..\src\login\account.h">
+			</File>
+			<File
+				RelativePath="..\src\login\account_rj.c">
+			</File>
+			<File
+				RelativePath="..\src\login\account_txt.c">
+			</File>
 			<File
 				RelativePath="..\src\login\admin.c">
 			</File>
+			<File
+				RelativePath="..\src\login\ipban.h">
+			</File>
+			<File
+				RelativePath="..\src\login\ipban_txt.c">
+			</File>
 			<File
 				RelativePath="..\src\login\login.c">
 			</File>
 			<File
 				RelativePath="..\src\login\login.h">
 			</File>
+			<File
+				RelativePath="..\src\login\loginlog.h">
+			</File>
+			<File
+				RelativePath="..\src\login\loginlog_txt.c">
+			</File>
 		</Filter>
 		<Filter
 			Name="common"

+ 12 - 25
vcproj-7.1/map-server_sql.vcproj

@@ -21,7 +21,7 @@
 				AdditionalOptions="/wd4018
 /wd4100"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;MAPREGSQL;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
@@ -41,10 +41,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib pcre.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib pcre.lib"
 				OutputFile="$(OutDir)\map-server_sql.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib;..\3rdparty\zlib\lib;..\3rdparty\pcre\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				IgnoreDefaultLibraryNames=""
 				GenerateDebugInformation="TRUE"
@@ -93,7 +93,7 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib;..\src\mysql"
+				AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;MAPREGSQL;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
@@ -107,10 +107,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib pcre.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib libmysql.lib zdll.lib pcre.lib"
 				OutputFile="$(OutDir)\map-server_sql.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\mysql\lib;..\3rdparty\zlib\lib;..\3rdparty\pcre\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				IgnoreDefaultLibraryNames=""
 				GenerateDebugInformation="TRUE"
@@ -271,15 +271,18 @@
 			<File
 				RelativePath="..\src\map\pc.h">
 			</File>
-			<File
-				RelativePath="..\src\map\pcre.h">
-			</File>
 			<File
 				RelativePath="..\src\map\pet.c">
 			</File>
 			<File
 				RelativePath="..\src\map\pet.h">
 			</File>
+			<File
+				RelativePath="..\src\map\quest.c">
+			</File>
+			<File
+				RelativePath="..\src\map\quest.h">
+			</File>
 			<File
 				RelativePath="..\src\map\script.c">
 			</File>
@@ -322,12 +325,6 @@
 			<File
 				RelativePath="..\src\map\vending.h">
 			</File>
-			<File
-				RelativePath="..\src\map\quest.c">
-			</File>
-			<File
-				RelativePath="..\src\map\quest.h">
-			</File>
 		</Filter>
 		<Filter
 			Name="common"
@@ -435,16 +432,6 @@
 				RelativePath="..\src\common\version.h">
 			</File>
 		</Filter>
-		<Filter
-			Name="zlib"
-			Filter="">
-			<File
-				RelativePath="..\src\zlib\zconf.h">
-			</File>
-			<File
-				RelativePath="..\src\zlib\zlib.h">
-			</File>
-		</Filter>
 	</Files>
 	<Globals>
 	</Globals>

+ 12 - 25
vcproj-7.1/map-server_txt.vcproj

@@ -21,7 +21,7 @@
 				AdditionalOptions="/wd4018
 /wd4100"
 				Optimization="0"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
+				AdditionalIncludeDirectories="..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				GeneratePreprocessedFile="0"
 				MinimalRebuild="TRUE"
@@ -42,10 +42,10 @@
 			<Tool
 				Name="VCLinkerTool"
 				AdditionalOptions="/FIXED:NO"
-				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib pcre.lib zdll.lib"
+				AdditionalDependencies="msvcrtd.lib oldnames.lib ws2_32.lib zdll.lib pcre.lib"
 				OutputFile="$(OutDir)\map-server.exe"
 				LinkIncremental="2"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\zlib\lib;..\3rdparty\pcre\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\map-server.pdb"
@@ -93,7 +93,7 @@
 				EnableFiberSafeOptimizations="TRUE"
 				OptimizeForProcessor="2"
 				OptimizeForWindowsApplication="TRUE"
-				AdditionalIncludeDirectories="..\src\common;..\src\zlib"
+				AdditionalIncludeDirectories="..\3rdparty\zlib\include;..\3rdparty\pcre\include"
 				PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;TXT_ONLY;FD_SETSIZE=4096;DB_MANUAL_CAST_TO_UNION"
 				StringPooling="TRUE"
 				RuntimeLibrary="3"
@@ -108,10 +108,10 @@
 				Name="VCCustomBuildTool"/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib pcre.lib zdll.lib"
+				AdditionalDependencies="msvcrt.lib oldnames.lib ws2_32.lib zdll.lib pcre.lib"
 				OutputFile="$(OutDir)\map-server.exe"
 				LinkIncremental="1"
-				AdditionalLibraryDirectories="..\lib"
+				AdditionalLibraryDirectories="..\3rdparty\zlib\lib;..\3rdparty\pcre\lib"
 				IgnoreAllDefaultLibraries="TRUE"
 				GenerateDebugInformation="TRUE"
 				ProgramDatabaseFile="$(OutDir)\map-server.pdb"
@@ -271,15 +271,18 @@
 			<File
 				RelativePath="..\src\map\pc.h">
 			</File>
-			<File
-				RelativePath="..\src\map\pcre.h">
-			</File>
 			<File
 				RelativePath="..\src\map\pet.c">
 			</File>
 			<File
 				RelativePath="..\src\map\pet.h">
 			</File>
+			<File
+				RelativePath="..\src\map\quest.c">
+			</File>
+			<File
+				RelativePath="..\src\map\quest.h">
+			</File>
 			<File
 				RelativePath="..\src\map\script.c">
 			</File>
@@ -322,12 +325,6 @@
 			<File
 				RelativePath="..\src\map\vending.h">
 			</File>
-			<File
-				RelativePath="..\src\map\quest.c">
-			</File>
-			<File
-				RelativePath="..\src\map\quest.h">
-			</File>
 		</Filter>
 		<Filter
 			Name="common"
@@ -429,16 +426,6 @@
 				RelativePath="..\src\common\version.h">
 			</File>
 		</Filter>
-		<Filter
-			Name="zlib"
-			Filter="">
-			<File
-				RelativePath="..\src\zlib\zconf.h">
-			</File>
-			<File
-				RelativePath="..\src\zlib\zlib.h">
-			</File>
-		</Filter>
 	</Files>
 	<Globals>
 	</Globals>

Some files were not shown because too many files changed in this diff