diff options
109 files changed, 6499 insertions, 5841 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index ada21ce57..5a1178a99 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -3,6 +3,23 @@ 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. +2007/09/20 + * Merged the tmpsql branch: [FlavioJS] + - Abstraction for the sql code (sql.c/h). + - New configure script and makefiles. + - Restored txt zeny logging code. (r10814) + - Rewrote mapserver's sql code - itemdb, mobdb, mapreg, logs. (r10814) + - Fixed a precedence issue (&& and ) in char_sql/char.c. (r10833) + - Improved db reading code a bit for consistency. (r11077) + - Added separate atcommand for mail deletion. (r11077) + - Corrected a few messages that said "new" instead of "unread". (r11077) + - Broadcast (*) messages now use "*" as the target's name (not ""). (r11077) + - Moved StringBuf code from utils.c/h to strlib.c/h. (r11084 r11117) + - Some misc login server cleanups (reformatting etc). (r11136) + - Corrected/modified some header entries. (r11141 r11147 11148) + - Adjusted VS project files. (r11147) + - Adjusted the way the sql charserver does item saving. (r11192) + - Corrected usage of reserved keyword 'friend' in mmo.h. (r11192) 2007/09/17 * Several skills with a splash area (except ground based ones) will now hit Ice-walls when casted by mobs. diff --git a/Makefile b/Makefile deleted file mode 100644 index 020ea5133..000000000 --- a/Makefile +++ /dev/null @@ -1,253 +0,0 @@ - -CACHED = $(shell ls | grep Makefile.cache) -ifeq ($(findstring Makefile.cache,$(CACHED)), Makefile.cache) -MKDEF = $(shell cat Makefile.cache) -else - -CC = gcc -pipe -# CC = g++ --pipe - -MAKE = make -# MAKE = gmake - -# Detecting gcc version -GCC_VERSION = $(shell $(CC) -v 2>&1 | grep version | cut -d' ' -f3 | cut -d'.' -f1) - -OPT = -g -OPT += -O2 -# OPT += -O3 -# OPT += -mmmx -# OPT += -msse -# OPT += -msse2 -# OPT += -msse3 -# OPT += -rdynamic -OPT += -ffast-math -# OPT += -fbounds-checking -# OPT += -fstack-protector -# OPT += -fomit-frame-pointer -OPT += -Wall -Wno-sign-compare -ifeq ($(GCC_VERSION), 4) - OPT += -Wno-unused-parameter -Wno-pointer-sign -endif -# Server Packet Protocol version (also defined in src/common/mmo.h) -# OPT += -DPACKETVER=8 -# Makes map-wide script variables be saved to SQL instead of TXT files. -# OPT += -DMAPREGSQL -# Enable the perl regular expression support for scripts -# OPT += -DPCRE_SUPPORT -# OPT += -DGCOLLECT -# OPT += -DMEMWATCH -# OPT += -DDMALLOC -DDMALLOC_FUNC_CHECK -# OPT += -DBCHECK - -# LIBS += -lgc -# LIBS += -ldmalloc -# LIBS += -L/usr/local/lib -lpcre - -PLATFORM = $(shell uname) -ARCH = $(shell uname -m) - -ifeq ($(findstring Linux,$(PLATFORM)), Linux) - LIBS += -ldl -endif - -ifeq ($(findstring SunOS,$(PLATFORM)), SunOS) - LIBS += -lsocket -lnsl -ldl - MAKE = gmake -endif - -ifeq ($(findstring FreeBSD,$(PLATFORM)), FreeBSD) - MAKE = gmake - OS_TYPE = -D__FREEBSD__ -endif - -ifeq ($(findstring NetBSD,$(PLATFORM)), NetBSD) - MAKE = gmake - OS_TYPE = -D__NETBSD__ -endif - -ifeq ($(findstring CYGWIN,$(PLATFORM)), CYGWIN) - OPT += -DFD_SETSIZE=4096 - OS_TYPE = -DCYGWIN -endif - -ifeq ($(findstring mingw,$(shell gcc --version)), mingw) - IS_MINGW = 1 - OS_TYPE = -DMINGW - OPT += -DFD_SETSIZE=4096 -# CFLAGS += -I../zlib -# LIBS += -L../../lib - LIBS += -lws2_32 -endif - - -ifeq ($(findstring x86_64,$(ARCH)), x86_64) - OPT += -m32 -endif - -CFLAGS = $(OPT) -I../common $(OS_TYPE) - -ifdef SQLFLAG - ifdef IS_MINGW - CFLAGS += -I../mysql - LIBS += -lmysql - else - MYSQLFLAG_CONFIG = $(shell which mysql_config) - ifeq ($(findstring /,$(MYSQLFLAG_CONFIG)), /) - MYSQLFLAG_VERSION = $(shell $(MYSQLFLAG_CONFIG) --version | sed s:\\..*::) - ifeq ($(findstring 5,$(MYSQLFLAG_VERSION)), 5) - MYSQLFLAG_CONFIG_ARGUMENT = --include - else - MYSQLFLAG_CONFIG_ARGUMENT = --cflags - endif - CFLAGS += $(shell $(MYSQLFLAG_CONFIG) $(MYSQLFLAG_CONFIG_ARGUMENT)) - LIBS += $(shell $(MYSQLFLAG_CONFIG) --libs) - else - CFLAGS += -I/usr/local/include/mysql - LIBS += -L/usr/local/lib/mysql -lmysqlclient - endif - endif -endif - -ifneq ($(findstring -lz,$(LIBS)), -lz) - LIBS += -lz -endif -ifneq ($(findstring -lm,$(LIBS)), -lm) - LIBS += -lm -endif - -MKDEF = CC="$(CC)" CFLAGS="$(CFLAGS)" LIB_S="$(LIBS)" - -endif - -.PHONY: txt sql common login login_sql char char_sql map map_sql ladmin converters \ - addons plugins tools clean depend - -txt : Makefile.cache conf common login char map ladmin - -ifdef SQLFLAG -sql: Makefile.cache conf common login_sql char_sql map_sql -else -sql: - $(MAKE) SQLFLAG=1 $@ -endif - -conf: - cp -r conf-tmpl conf - cp -r save-tmpl save - rm -rf conf/.svn conf/*/.svn save/.svn - -common: src/common/GNUmakefile - $(MAKE) -C src/$@ $(MKDEF) - -login: src/login/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) txt - -char: src/char/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) txt - -map: src/map/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) txt - -login_sql: src/login_sql/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) sql - -char_sql: src/char_sql/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) sql - -map_sql: src/map/GNUmakefile common - $(MAKE) -C src/map $(MKDEF) sql - -ladmin: src/ladmin/GNUmakefile common - $(MAKE) -C src/$@ $(MKDEF) - -plugins addons: src/plugins/GNUmakefile common - $(MAKE) -C src/plugins $(MKDEF) - -tools: - $(MAKE) -C src/tool $(MKDEF) - -ifdef SQLFLAG -converters: src/txt-converter/GNUmakefile common - $(MAKE) -C src/txt-converter $(MKDEF) -else -converters: - $(MAKE) SQLFLAG=1 $@ -endif - -clean: src/common/GNUmakefile src/login/GNUmakefile src/login_sql/GNUmakefile \ - src/char/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile \ - src/ladmin/GNUmakefile src/plugins/GNUmakefile src/txt-converter/GNUmakefile - rm -f Makefile.cache - $(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 $@ - $(MAKE) -C src/ladmin $@ - $(MAKE) -C src/plugins $@ - $(MAKE) -C src/txt-converter $@ - -depend: src/common/GNUmakefile src/login/GNUmakefile src/login_sql/GNUmakefile \ - src/char/GNUmakefile src/char_sql/GNUmakefile src/map/GNUmakefile \ - src/ladmin/GNUmakefile src/plugins/GNUmakefile src/txt-converter/GNUmakefile - cd src/common; makedepend -fGNUmakefile -pobj/ -Y. *.c; cd ../..; - cd src/login; makedepend -DTXT_ONLY -fGNUmakefile -Y. -Y../common *.c; cd ../..; - cd src/login_sql; makedepend -fGNUmakefile -Y. -Y../common *.c; cd ../..; - cd src/char; makedepend -DTXT_ONLY -fGNUmakefile -Y. -Y../common *.c; cd ../..; - cd src/char_sql; makedepend -fGNUmakefile -Y. -Y../common *.c; cd ../..; - cd src/map; makedepend -DTXT_ONLY -fGNUmakefile -ptxtobj/ -Y. -Y../common *.c; cd ../..; - cd src/map; makedepend -fGNUmakefile -a -psqlobj/ -Y. -Y../common *.c; cd ../..; - cd src/ladmin; makedepend -fGNUmakefile -Y. -Y../common *.c; cd ../..; - cd src/txt-converter; makedepend -DTXT_SQL_CONVERT -fGNUmakefile -Y. -Y../common *.c; cd ../..; - $(MAKE) -C src/plugins $@ - -Makefile.cache: - printf "$(subst ",\",$(MKDEF))" > Makefile.cache - -src/%/GNUmakefile: src/%/Makefile - sed -e 's/$$>/$$^/' $< > $@ - -src/common/GNUmakefile: src/common/Makefile -src/login/GNUmakefile: src/login/Makefile -src/login_sql/GNUmakefile: src/login_sql/Makefile -src/char/GNUmakefile: src/char/Makefile -src/char_sql/GNUmakefile: src/char_sql/Makefile -src/map/GNUmakefile: src/map/Makefile -src/plugins/GNUmakefile: src/plugins/Makefile -src/ladmin/GNUmakefile: src/ladmin/Makefile -src/txt-converter/GNUmakefile: src/txt-converter/Makefile - -install: conf/%.conf conf/%.txt - $(shell mkdir -p /opt/eathena/bin/) - $(shell mkdir -p /opt/eathena/etc/eathena/) - $(shell mkdir -p /opt/eathena/var/log/eathena/) - $(shell mv save /opt/eathena/etc/eathena/save) - $(shell mv db /opt/eathena/etc/eathena/db) - $(shell mv conf /opt/eathena/etc/eathena/conf) - $(shell mv npc /opt/eathena/etc/eathena/npc) - $(shell mv log/* /opt/eathena/var/log/eathena/) - $(shell cp *-server* /opt/eathena/bin/) - $(shell cp ladmin /opt/eathena/bin/) - $(shell ln -s /opt/eathena/etc/eathena/save/ /opt/eathena/bin/) - $(shell ln -s /opt/eathena/etc/eathena/db/ /opt/eathena/bin/) - $(shell ln -s /opt/eathena/etc/eathena/conf/ /opt/eathena/bin/) - $(shell ln -s /opt/eathena/etc/eathena/npc/ /opt/eathena/bin/) - $(shell ln -s /opt/eathena/var/log/eathena/ /opt/eathena/bin/log) - -bin-clean: - $(shell rm /opt/eathena/bin/login-server*) - $(shell rm /opt/eathena/bin/char-server*) - $(shell rm /opt/eathena/bin/map-server*) - $(shell rm /opt/eathena/bin/ladmin) - -uninstall: - bin-clean - $(shell rm /opt/eathena/bin/save) - $(shell rm /opt/eathena/bin/db) - $(shell rm /opt/eathena/bin/conf) - $(shell rm /opt/eathena/bin/npc) - $(shell rm /opt/eathena/bin/log) - $(shell rm -rf /opt/eathena/etc/eathena) - $(shell rm -rf /opt/eathena/var/log/eathena) diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..a1075c85a --- /dev/null +++ b/Makefile.in @@ -0,0 +1,181 @@ +@SET_MAKE@ + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + ALL_DEPENDS=common common_sql login login_sql char char_sql map map_sql ladmin tools converters plugins conf + SQL_DEPENDS=common_sql login_sql char_sql map_sql conf + COMMON_SQL_DEPENDS= + LOGIN_SQL_DEPENDS=common_sql + CHAR_SQL_DEPENDS=common_sql + MAP_SQL_DEPENDS=common_sql + CONVERTERS_DEPENDS=common_sql +else + ALL_DEPENDS=common login char map ladmin tools plugins conf + SQL_DEPENDS=needs_mysql + COMMON_SQL_DEPENDS=needs_mysql + LOGIN_SQL_DEPENDS=needs_mysql + CHAR_SQL_DEPENDS=needs_mysql + MAP_SQL_DEPENDS=needs_mysql + CONVERTERS_DEPENDS=needs_mysql +endif + +##################################################################### +.PHONY: txt sql common common_sql login login_sql char char_sql map map_sql \ + ladmin tools converters plugins addons conf clean help depend + +all: $(ALL_DEPENDS) + +txt: common login char map conf + +sql: $(SQL_DEPENDS) + +common: + @$(MAKE) -C src/common txt + +common_sql: $(COMMON_SQL_DEPENDS) + @$(MAKE) -C src/common sql + +login: common + @$(MAKE) -C src/login + +login_sql: $(LOGIN_SQL_DEPENDS) + @$(MAKE) -C src/login_sql + +char: common + @$(MAKE) -C src/char + +char_sql: $(CHAR_SQL_DEPENDS) + @$(MAKE) -C src/char_sql + +map: common + @$(MAKE) -C src/map txt + +map_sql: $(MAP_SQL_DEPENDS) + @$(MAKE) -C src/map sql + +ladmin: common + @$(MAKE) -C src/ladmin + +tools: + @$(MAKE) -C src/tool + +converters: $(CONVERTERS_DEPENDS) + @$(MAKE) -C src/txt-converter + +plugins addons: common + @$(MAKE) -C src/plugins + +conf: +# conf: +# 1) create conf and conf/import folders +# 2) add missing import files +# 3) copy the rest of the files and folders +# 4) remove remaining .svn folders + @echo "building conf folder..." + @if test ! -d conf ; then mkdir conf ; fi + @if test ! -d conf/import ; then mkdir conf/import ; fi + @for f in $$(ls conf-tmpl/import) ; do if test ! -e conf/import/$$f ; then cp conf-tmpl/import/$$f conf/import ; fi ; done + @for f in $$(ls conf-tmpl) ; do if test "$$f" != "import" ; then cp -rf conf-tmpl/$$f conf ; fi ; done + @rm -rf conf/*/.svn +# save: +# 1) create save folder +# 2) add missing files + @echo "building save folder..." + @if test ! -d save ; then mkdir save ; fi + @for f in $$(ls save-tmpl) ; do if test ! -e save/$$f ; then cp save-tmpl/$$f save ; fi ; done + +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 $@ + @$(MAKE) -C src/ladmin $@ + @$(MAKE) -C src/plugins $@ + @$(MAKE) -C src/tool $@ + @$(MAKE) -C src/txt-converter $@ + +help: + @echo "most common targets are 'all' 'txt' 'sql' 'clean' 'help'" + @echo "possible targets are:" + @echo "'common' - builds object files used in TXT servers" + @echo "'common_sql' - builds object files used in SQL servers" + @echo "'login' - builds login server (TXT version)" + @echo "'login_sql' - builds login server (SQL version)" + @echo "'char' - builds char server (TXT version)" + @echo "'char_sql' - builds char server (SQL version)" + @echo "'map' - builds map server (TXT version)" + @echo "'map_sql' - builds map server (SQL version)" + @echo "'ladmin' - builds remote administration tool" + @echo "'tools' - builds all the tools in src/tools" + @echo "'converters' - builds the login/char converters" + @echo "'plugins' - builds all the plugins in src/plugins" + @echo "'addons'" + @echo "'conf' - builds conf and save folders from the templates" + @echo "'all' - builds all above targets" + @echo "'txt' - builds txt servers (targets 'common' 'login' 'char' 'map' and" + @echo " 'conf')" + @echo "'sql' - builds sql servers (targets 'common_sql' 'login_sql' 'char_sql'" + @echo " 'map_sql' and 'conf')" + @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 + +##################################################################### +# TODO + +# Server Packet Protocol version (also defined in src/common/mmo.h) +# CFLAGS += -DPACKETVER=8 + +# Makes map-wide script variables be saved to SQL instead of TXT files. +# CFLAGS += -DMAPREGSQL + +# OPT += -DGCOLLECT +# LIBS += -lgc + +# OPT += -DMEMWATCH + +# OPT += -DDMALLOC -DDMALLOC_FUNC_CHECK +# LIBS += -ldmalloc + +# OPT += -DBCHECK + + +install: conf/%.conf conf/%.txt + $(shell mkdir -p /opt/eathena/bin/) + $(shell mkdir -p /opt/eathena/etc/eathena/) + $(shell mkdir -p /opt/eathena/var/log/eathena/) + $(shell mv save /opt/eathena/etc/eathena/save) + $(shell mv db /opt/eathena/etc/eathena/db) + $(shell mv conf /opt/eathena/etc/eathena/conf) + $(shell mv npc /opt/eathena/etc/eathena/npc) + $(shell mv log/* /opt/eathena/var/log/eathena/) + $(shell cp *-server* /opt/eathena/bin/) + $(shell cp ladmin /opt/eathena/bin/) + $(shell ln -s /opt/eathena/etc/eathena/save/ /opt/eathena/bin/) + $(shell ln -s /opt/eathena/etc/eathena/db/ /opt/eathena/bin/) + $(shell ln -s /opt/eathena/etc/eathena/conf/ /opt/eathena/bin/) + $(shell ln -s /opt/eathena/etc/eathena/npc/ /opt/eathena/bin/) + $(shell ln -s /opt/eathena/var/log/eathena/ /opt/eathena/bin/log) + +bin-clean: + $(shell rm /opt/eathena/bin/login-server*) + $(shell rm /opt/eathena/bin/char-server*) + $(shell rm /opt/eathena/bin/map-server*) + $(shell rm /opt/eathena/bin/ladmin) + +uninstall: + bin-clean + $(shell rm /opt/eathena/bin/save) + $(shell rm /opt/eathena/bin/db) + $(shell rm /opt/eathena/bin/conf) + $(shell rm /opt/eathena/bin/npc) + $(shell rm /opt/eathena/bin/log) + $(shell rm -rf /opt/eathena/etc/eathena) + $(shell rm -rf /opt/eathena/var/log/eathena) diff --git a/conf-tmpl/msg_athena.conf b/conf-tmpl/msg_athena.conf index 88967c26a..851350300 100644 --- a/conf-tmpl/msg_athena.conf +++ b/conf-tmpl/msg_athena.conf @@ -436,9 +436,9 @@ 511: %d - From : %s (New - Priority) 512: %d - From : %s (New) 513: %d - From : %s -514: You have %d new messages. +514: You have %d unread messages. 515: You have %d unread priority messages. -516: You have no new messages. +516: You have no unread messages. 517: Message not found. 518: Reading message from %s. 519: Cannot delete unread priority mail. diff --git a/configure b/configure deleted file mode 100644 index b50031368..000000000 --- a/configure +++ /dev/null @@ -1,256 +0,0 @@ -#!/bin/bash -## NOTE: -## I know this is not a clean way to check for some stuff -## and edit the Makefile, but hey, it does work! - -# Configure script for eAthena -# Copyright (C) 2005 dontBR -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -# Default variables -status_mmx="No" -status_sse="No" -status_sse2="No" -status_sse3="No" -status_pcre="No" -prefix='/opt/eathena/' - -# Functions -function check_sed { - echo -n "Checking for sed... " - if [ -f $(which sed) ]; then - echo "yes" - else - echo "Error: sed not found in $PATH" - exit 1 - fi -} - -function check_gcc { - echo -n "Checking for gcc... " - if [ -f $(which gcc) ]; then - echo "yes" - else - echo "Error: GCC not found in $PATH" - exit 1 - fi -} - -function check_make { - echo -n "Checking for (g)make... " - if [ -f $(which make) ]; then - maker=make - echo "yes" - else if [ -f $(which gmake) ]; then - maker=gmake - echo "yes" - else - echo "Error: (g)make not found in $PATH" - exit 1 - fi - fi -} - -function check_sockets { - echo -n "Checking for sockets... " - echo "#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -int main(){ -}" > test_sockets.c - if $(gcc test_sockets.c -o test_sockets); then - echo "yes" - rm -f test_sockets.c test_sockets - else - echo "Error: Unix sockets not found/working." - exit 1 - rm -f test_sockets.c - fi -} - -function check_mysql_headers { - echo -n "Checking for MySQL headers... " - if [ -d /usr/local/lib/mysql ]; then # Default - echo "yes" - mysql_headers_path='/usr/local/lib/mysql' - else - if [ -d /usr/include/mysql ]; then # Gentoo/Debian/? - echo "yes" - mysql_headers_path='/usr/include/mysql' - else - echo "Error: MySQL headers not found." - mysql_headers_path='Not found.' - fi - fi -} - -function optimize { - case $@ in - mmx ) status_mmx="Yes" ;; - sse ) status_sse="Yes" ;; - sse2 ) status_sse2="Yes" ;; - sse3 ) status_sse3="Yes" ;; - all ) status_mmx="Yes" - status_sse="Yes" - status_sse2="Yes" - status_sse3="Yes" ;; - esac -} - -function make_changes { - if [ "$maker" != "make" ]; then - sed -e 's,MAKE = make,MAKE = '$maker',g' Makefile -i - fi - if [ "$status_mmx" = "Yes" ]; then - sed -e 's,# OPT += -mmmx,OPT += -mmmx,g' Makefile -i - fi - if [ "$status_sse" = "Yes" ]; then - sed -e 's,# OPT += -msse,OPT += -msse,g' Makefile -i - fi - if [ "$status_sse2" = "Yes" ]; then - sed -e 's,# OPT += -msse2,OPT += -msse2,g' Makefile -i - fi - if [ "$status_sse3" = "Yes" ]; then - sed -e 's,# OPT += -msse3,OPT += -msse3,g' Makefile -i - fi - if [ "$status_pcre" = "Yes" ]; then - sed -e 's,# OPT += -DPCRE_SUPPORT,OPT += -DPCRE_SUPPORT,g' Makefile -i - fi - if [ "$mysql_headers_path" != "/usr/local/lib/mysql" ] && [ "$mysql_headers_path" != "Not found." ]; then - sed -e 's,LIBS += -L/usr/local/lib/mysql -lmysqlclient,LIBS += -L'$mysql_headers_path' -lmysqlclient,g' Makefile -i - fi -} - -function opt_check_pcre { - echo -n "Checking for PCRE... " - if [ -f /usr/local/lib/pcre.h ]; then - echo "yes" - status_pcre="Yes" - else - echo "Error: PCRE not found." - status_pcre="No" - fi -} - -function make_report { - echo "Configuration report:" - echo eAthena - - echo - echo Enable PCRE support..... : $status_pcre - echo - echo Enable MMX optimization. : $status_mmx - echo Enable SSE optimization. : $status_sse - echo Enable SSE2 optimization : $status_sse2 - echo Enable SSE3 optimization : $status_sse3 - echo - echo MySQL headers path...... : $mysql_headers_path - echo - echo eAthena will be installed in $prefix - echo Please type \'make txt\' or \'make sql\' now to compile eAthena. -} - -function helptext { - echo "eAthena Configure Script version 0.1" - echo - echo "Options:" - echo - echo " -h Display this help message and exit." - echo " -d Enter debug mode." - echo " -o Turn on optimization flags." - echo " Supported:" - echo " mmx" - echo " sse" - echo " sse2" - echo " sse3" - echo " all" - echo " -e Enable PCRE support." - echo " -p Root directory where eA is going to be installed." - echo " DON'T FORGET THE LAST SLASH!" - echo " For example:" - echo " ./configure -p /usr/local/" - echo " This will create /usr/local/bin/login-server," - echo " /usr/local/etc/eathena/save/account.txt, etc" - echo " Default is /opt/eathena/" - echo - echo "Report bugs (about the configure script) to dontBR at the eAthena Support Board." -} - -function make_installable { - echo -e '' >> Makefile - echo -e 'install: conf/%.conf conf/%.txt' >> Makefile - echo -e ' $(shell mkdir -p '$prefix'bin/)' >> Makefile - echo -e ' $(shell mkdir -p '$prefix'etc/eathena/)' >> Makefile - echo -e ' $(shell mkdir -p '$prefix'var/log/eathena/)' >> Makefile - echo -e ' $(shell mv save '$prefix'etc/eathena/save)' >> Makefile - echo -e ' $(shell mv db '$prefix'etc/eathena/db)' >> Makefile - echo -e ' $(shell mv conf '$prefix'etc/eathena/conf)' >> Makefile - echo -e ' $(shell mv npc '$prefix'etc/eathena/npc)' >> Makefile - echo -e ' $(shell mv log/* '$prefix'var/log/eathena/)' >> Makefile - echo -e ' $(shell cp *-server* '$prefix'bin/)' >> Makefile - echo -e ' $(shell cp ladmin '$prefix'bin/)' >> Makefile - echo -e ' $(shell ln -s '$prefix'etc/eathena/save/ '$prefix'bin/)' >> Makefile - echo -e ' $(shell ln -s '$prefix'etc/eathena/db/ '$prefix'bin/)' >> Makefile - echo -e ' $(shell ln -s '$prefix'etc/eathena/conf/ '$prefix'bin/)' >> Makefile - echo -e ' $(shell ln -s '$prefix'etc/eathena/npc/ '$prefix'bin/)' >> Makefile - echo -e ' $(shell ln -s '$prefix'var/log/eathena/ '$prefix'bin/log)' >> Makefile - echo '' >> Makefile - echo -e 'bin-clean:' >> Makefile - echo -e ' $(shell rm '$prefix'bin/login-server*)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/char-server*)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/map-server*)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/ladmin)' >> Makefile - echo '' >> Makefile - echo -e 'uninstall:' >> Makefile - echo -e ' bin-clean' >> Makefile - echo -e ' $(shell rm '$prefix'bin/save)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/db)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/conf)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/npc)' >> Makefile - echo -e ' $(shell rm '$prefix'bin/log)' >> Makefile - echo -e ' $(shell rm -rf '$prefix'etc/eathena)' >> Makefile - echo -e ' $(shell rm -rf '$prefix'var/log/eathena)' >> Makefile -} - - -# Arguments -while getopts ":hdo:ep:" opt; do - case $opt in - h ) helptext ; exit ;; - d ) set -x ;; - o ) optimize ${OPTARG} ;; - e ) opt_check_pcre ;; - p ) prefix=${OPTARG} ; [ -d ${OPTARG} ] || echo "The directory $prefix does not exist. Creating...";; - esac -done - - -# Execution -echo "eAthena configure script" -echo "Note: This is ALPHA software! Do NOT use it on a production server!" -echo -echo "Checking for dependencies.." -check_sed -check_gcc -check_make -check_sockets -check_mysql_headers -make_changes -make_installable -echo -make_report -exit diff --git a/configure.in b/configure.in new file mode 100644 index 000000000..080df746b --- /dev/null +++ b/configure.in @@ -0,0 +1,295 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT(eAthena) +AC_REVISION($Revision$) +AC_PREREQ([2.61]) +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/map/Makefile src/plugins/Makefile src/tool/Makefile]) + + +# +# Enable/disable MySql and optionally specify the path (optional library) +# +AC_ARG_WITH( + [mysql], + AC_HELP_STRING( + [--with-mysql=@<:@ARG@:>@], + [use MySQL client library @<:@default=yes@:>@, optionally specify path to the mysql_config executable] + ), + [ + if test "$withval" = "no" ; then + want_mysql="no" + elif test "$withval" = "yes" ; then + want_mysql="yes" + else + want_mysql="yes" + MYSQL_CONFIG_HOME="$withval" + fi + ], + [want_mysql="yes"] +) + + +# +# Enable/disable PCRE and optionally specify the path (optional library) +# +AC_ARG_WITH( + [pcre], + AC_HELP_STRING( + [--with-pcre=@<:@ARG@:>@], + [use PCRE library @<:@default=yes@:>@, optionally specify the root directory path of pcre installation] + ), + [ + if test "$withval" = "no" ; then + want_pcre="no" + elif test "$withval" = "yes" ; then + want_pcre="yes" + else + want_pcre="yes" + PCRE_HOME="$withval" + fi + ], + [want_pcre="yes"] +) + + +# +# Specify the path of the zlib library (required library) +# +AC_ARG_WITH( + [zlib], + AC_HELP_STRING( + [--with-zlib=DIR], + [root directory path of zlib installation (defaults to /usr/local or /usr if not found in /usr/local)] + ), + [ + test -n "$withval" && ZLIB_HOME="$withval" + ], + [ + ZLIB_HOME=/usr/local + test ! -f "${ZLIB_HOME}/include/zlib.h" && ZLIB_HOME=/usr + ] +) + + + +############################################################################### +# Checks for programs and types. + +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_CPP +AC_LANG([C]) + + +CFLAGS="$CFLAGS -pipe -ffast-math -Wall -Wno-sign-compare" +CPPFLAGS="$CPPFLAGS -I../common" + + +AC_C_BIGENDIAN( + [AC_MSG_ERROR([[bigendian is not supported... stopping]])], + , + [AC_MSG_WARN([[unable to determine endianess, only little endian is supported]])] +) + + +AC_MSG_CHECKING([whether pointers can be stored in ints (old code)]) +pointers_fit_in_ints="no" +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[int hw[(sizeof(int) == sizeof(void *))];]])], + [pointers_fit_in_ints="yes"], + [] +) +if test "$pointers_fit_in_ints" = "no" ; then + CFLAGS="$CFLAGS -m32" + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[int hw[(sizeof(int) == sizeof(void *))];]])], + [pointers_fit_in_ints="yes (with -m32)"], + [] + ) +fi +AC_MSG_RESULT($pointers_fit_in_ints) +if test "$pointers_fit_in_ints" = "no" ; then + AC_MSG_ERROR([pointers cannot be stored in ints, required for old code... stopping]) +fi + + +AC_MSG_CHECKING([whether $CC supports -Wno-unused-parameter]) +OLD_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -Wno-unused-parameter" +AC_COMPILE_IFELSE( + [int foo;], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + CFLAGS="$OLD_CFLAGS" + ] +) + + +AC_MSG_CHECKING([whether $CC supports -Wno-pointer-sign]) +OLD_CFLAGS="$CFLAGS" +CFLAGS="$CPPFLAGS -Wno-pointer-sign" +AC_COMPILE_IFELSE( + [int foo;], + [AC_MSG_RESULT([yes])], + [ + AC_MSG_RESULT([no]) + CFLAGS="$OLD_CFLAGS" + ] +) + + +############################################################################### +# Checks for libraries and header files. + + + +dnl +dnl Check MySQL library (optional) +dnl + +MYSQL_VERSION="" +MYSQL_CFLAGS="" +MYSQL_LIBS="" + +if test "$want_mysql" = "no" ; then + AC_MSG_NOTICE([ignoring MySQL (optional)]) +else + if test -z "$MYSQL_CONFIG_HOME" -o test; then + AC_PATH_PROG([MYSQL_CONFIG_HOME], [mysql_config], [no]) + fi + + AC_MSG_CHECKING([MySQL library (optional)]) + if test "$MYSQL_CONFIG_HOME" != "no" ; then + HAVE_MYSQL="yes" + MYSQL_VERSION="`$MYSQL_CONFIG_HOME --version`" + MYSQL_CFLAGS="`$MYSQL_CONFIG_HOME --cflags`" + MYSQL_LIBS="`$MYSQL_CONFIG_HOME --libs`" + AC_MSG_RESULT([yes ($MYSQL_VERSION)]) + else + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([disabling MySQL (optional)]) + fi +fi + +AC_SUBST([HAVE_MYSQL]) +AC_SUBST([MYSQL_VERSION]) +AC_SUBST([MYSQL_CFLAGS]) +AC_SUBST([MYSQL_LIBS]) + + + +dnl +dnl Check PCRE libraries (optional) +dnl + +##TODO PCRE version +PCRE_LIBS="" +PCRE_CFLAGS="" + +if test "$want_pcre" = "no" ; then + AC_MSG_NOTICE([ignoring PCRE (optional)]) +else + if test -z "$PCRE_HOME" ; then + AC_CHECK_LIB([pcre], [pcre_study], [HAVE_PCRE="yes"], []) + if test "$HAVE_PCRE" = "yes" ; then + PCRE_LIBS="-lpcre" + fi + else + PCRE_OLD_LDFLAGS="$LDFLAGS" ; LDFLAGS="$LDFLAGS -L$PCRE_HOME/lib" + PCRE_OLD_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="$CPPFLAGS -I$PCRE_HOME/include" + AC_CHECK_LIB(pcre, pcre_compile, [HAVE_PCRE="yes"], []) + CPPFLAGS="$PCRE_OLD_CPPFLAGS" + LDFLAGS="$PCRE_OLD_LDFLAGS" + if test "$HAVE_PCRE" = "yes" ; then + PCRE_LIBS="-L$PCRE_HOME/lib -lpcre" + test -d "$PCRE_HOME/include" && PCRE_CFLAGS="-I$PCRE_HOME/include" + fi + fi + AC_MSG_CHECKING([PCRE library (optional)]) + if test "$HAVE_PCRE" = "yes" ; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([disabling PCRE (optional)]) + fi +fi + +AC_SUBST([HAVE_PCRE]) +AC_SUBST([PCRE_LIBS]) +AC_SUBST([PCRE_CFLAGS]) + + + +dnl +dnl zlib library (required) +dnl + +if test -n "${ZLIB_HOME}" ; then + LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" + CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" +fi +AC_CHECK_LIB([z], [inflateEnd], ,[AC_MSG_ERROR([zlib library not found, please specify the correct path with --with-zlib=DIR... stopping])]) +AC_CHECK_HEADER([zlib.h], , [AC_MSG_ERROR([zlib header not found, please specify the correct path with --with-zlib=DIR... stopping])]) + + + +dnl +dnl math library (required) +dnl + +AC_CHECK_LIB([m], [sqrt], [], [AC_MSG_ERROR([math library not found... stopping])]) + + + +dnl +dnl Host specific stuff +dnl + +AC_MSG_CHECKING([host OS]) +host_os="`uname`" +AC_MSG_RESULT([$host_os]) +fd_setsize="" +DLLEXT=".so" +case $host_os in +Solaris* ) + LIBS="$LIBS -lsocket -lnsl -ldl" + ;; +Linux* ) + LIBS="$LIBS -ldl" + ;; +FreeBSD*) + CPPFLAGS="$CPPFLAGS -D__FREEBSD__" + ;; +NetBSD*) + CPPFLAGS="$CPPFLAGS -D__NETBSD__" + ;; +CYGWIN*) + CPPFLAGS="$CPPFLAGS -DFD_SETSIZE=4096 -DCYGWIN" + fd_setsize="done" + DLLEXT=".dll" + ;; +esac +AC_SUBST([DLLEXT]) + +AC_MSG_CHECKING([for MinGW]) +if test -n "`$CC --version | grep -i mingw`" ; then + AC_MSG_RESULT([yes]) + CPPFLAGS="$CPPFLAGS -DMINGW" + if test -z "$fd_setsize" ; then + CPPFLAGS="$CPPFLAGS -DFD_SETSIZE=4096" + fi + LIBS="$LIBS -lws2_32" +else + AC_MSG_RESULT([no]) +fi + + + +############################################################################### +AC_OUTPUT diff --git a/eAthena-8.sln b/eAthena-8.sln index 4411e95ea..c6f05d3d6 100644 --- a/eAthena-8.sln +++ b/eAthena-8.sln @@ -117,15 +117,23 @@ Global {D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32 {D356871D-58E1-450B-967A-E9E9646175AF}.Debug|Win32.Build.0 = Debug|Win32 {D356871D-58E1-450B-967A-E9E9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32 + {D356871D-58E1-450B-967A-E9E9646175AF}.Debug-txt|Win32.ActiveCfg = Debug|Win32 + {D356871D-58E1-450B-967A-E9E9646175AF}.Debug-txt|Win32.Build.0 = Debug|Win32 {D356871D-58E1-450B-967A-E9E9646175AF}.Release|Win32.ActiveCfg = Release|Win32 {D356871D-58E1-450B-967A-E9E9646175AF}.Release|Win32.Build.0 = Release|Win32 {D356871D-58E1-450B-967A-E9E9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32 + {D356871D-58E1-450B-967A-E9E9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32 + {D356871D-58E1-450B-967A-E9E9646175AF}.Release-txt|Win32.Build.0 = Release|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Debug|Win32.ActiveCfg = Debug|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Debug|Win32.Build.0 = Debug|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Debug-sql|Win32.ActiveCfg = Debug|Win32 + {D356871D-58E1-450B-967A-EAE9646175AF}.Debug-txt|Win32.ActiveCfg = Debug|Win32 + {D356871D-58E1-450B-967A-EAE9646175AF}.Debug-txt|Win32.Build.0 = Debug|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Release|Win32.ActiveCfg = Release|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Release|Win32.Build.0 = Release|Win32 {D356871D-58E1-450B-967A-EAE9646175AF}.Release-sql|Win32.ActiveCfg = Release|Win32 + {D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.ActiveCfg = Release|Win32 + {D356871D-58E1-450B-967A-EAE9646175AF}.Release-txt|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/char/Makefile b/src/char/Makefile.in index 17b66b810..78d2cb2c8 100644 --- a/src/char/Makefile +++ b/src/char/Makefile.in @@ -1,5 +1,3 @@ -all txt: char-server - COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ @@ -7,21 +5,38 @@ COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ ../common/obj/mapindex.o ../common/obj/ers.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/malloc.h ../common/showmsg.h ../common/utils.h \ + ../common/strlib.h ../common/grfio.h \ + ../common/mapindex.h ../common/ers.h -%.o: %.c - $(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $< - -char-server: char.o inter.o int_party.o int_guild.o int_status.o int_storage.o int_pet.o int_homun.o $(COMMON_OBJ) - $(CC) -o ../../$@ $> $(LIB_S) +CHAR_OBJ = char.o inter.o int_party.o int_guild.o int_storage.o int_status.o int_pet.o int_homun.o + +##################################################################### +.PHONY : all char-server clean help + +all: char-server + +char-server: $(CHAR_OBJ) $(COMMON_OBJ) + @CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) @LIBS@ clean: - rm -f *.o ../../char-server GNUmakefile + rm -f *.o ../../char-server@EXEEXT@ + +help: + @echo "possible targets are 'char-server' 'all' 'clean' 'help'" + @echo "'char-server' - char server (TXT version)" + @echo "'all' - builds all above targets" + @echo "'clean' - cleans builds and objects" + @echo "'help' - outputs this message" + +##################################################################### + +%.o: %.c + @CC@ @CFLAGS@ -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # DO NOT DELETE -char.o: char.c char.h inter.h int_pet.h $(COMMON_H) ../common/version.h +char.o: char.c char.h inter.h int_pet.h $(COMMON_H) inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h char.h $(COMMON_H) int_party.o: int_party.c int_party.h inter.h char.h $(COMMON_H) int_guild.o: int_guild.c int_guild.h int_storage.h inter.h char.h $(COMMON_H) diff --git a/src/char/char.c b/src/char/char.c index ba21cd68e..9ef31871d 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -11,17 +11,19 @@ #include "../common/strlib.h" #include "../common/showmsg.h" #include "../common/timer.h" +#include "../common/lock.h" +#include "../common/malloc.h" +#include "../common/mapindex.h" +#include "../common/showmsg.h" +#include "../common/utils.h" #include "../common/version.h" - #include "inter.h" #include "int_guild.h" #include "int_homun.h" #include "int_pet.h" #include "int_party.h" #include "int_storage.h" -#ifdef ENABLE_SC_SAVING #include "int_status.h" -#endif #include "char.h" #include <sys/types.h> diff --git a/src/char/char.h b/src/char/char.h index ded9a9b2e..72077ac09 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -5,7 +5,6 @@ #define _CHAR_H_ #include "../common/mmo.h" -#include "../common/mapindex.h" #define START_CHAR_NUM 150000 #define MAX_MAP_SERVERS 30 @@ -21,7 +20,7 @@ struct character_data { struct mmo_charstatus* search_character(int aid, int cid); struct mmo_charstatus* search_character_byname(char* character_name); int search_character_index(char* character_name); -char * search_character_name(int index); +char* search_character_name(int index); int search_character_online(int aid, int cid); int mapif_sendall(unsigned char *buf, unsigned int len); diff --git a/src/char/int_guild.c b/src/char/int_guild.c index c4ae0a493..52514692c 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - #include "../common/cbasetypes.h" #include "../common/mmo.h" #include "../common/malloc.h" @@ -17,6 +13,10 @@ #include "int_storage.h" #include "int_guild.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + char guild_txt[1024] = "save/guild.txt"; char castle_txt[1024] = "save/castle.txt"; diff --git a/src/char/int_guild.h b/src/char/int_guild.h index 6b0e9f7b5..06293eb0f 100644 --- a/src/char/int_guild.h +++ b/src/char/int_guild.h @@ -4,6 +4,9 @@ #ifndef _INT_GUILD_H_ #define _INT_GUILD_H_ +struct guild; +struct guild_castle; + int inter_guild_init(void); void inter_guild_final(void); int inter_guild_save(void); diff --git a/src/char/int_homun.c b/src/char/int_homun.c index 684601449..35f8f9c50 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/socket.h" @@ -15,6 +11,10 @@ #include "inter.h" #include "int_homun.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + char homun_txt[1024]="save/homun.txt"; static struct dbt *homun_db; diff --git a/src/char/int_homun.h b/src/char/int_homun.h index d56ab97a9..1858ed4ba 100644 --- a/src/char/int_homun.h +++ b/src/char/int_homun.h @@ -8,7 +8,6 @@ int inter_homun_init(void); void inter_homun_final(void); int inter_homun_save(void); int inter_homun_delete(int homun_id); - int inter_homun_parse_frommap(int fd); extern char homun_txt[1024]; diff --git a/src/char/int_party.c b/src/char/int_party.c index b47a8b59c..96181cd1b 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #include "../common/cbasetypes.h" #include "../common/mmo.h" #include "../common/malloc.h" @@ -16,6 +12,10 @@ #include "inter.h" #include "int_party.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + char party_txt[1024] = "save/party.txt"; #ifndef TXT_SQL_CONVERT struct party_data { diff --git a/src/char/int_party.h b/src/char/int_party.h index 453699617..ad724e475 100644 --- a/src/char/int_party.h +++ b/src/char/int_party.h @@ -4,12 +4,12 @@ #ifndef _INT_PARTY_H_ #define _INT_PARTY_H_ +struct party; + int inter_party_init(void); void inter_party_final(void); int inter_party_save(void); - int inter_party_parse_frommap(int fd); - int inter_party_leave(int party_id,int account_id, int char_id); extern char party_txt[1024]; diff --git a/src/char/int_pet.c b/src/char/int_pet.c index b15e8e259..e7ff2aff2 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/socket.h" @@ -15,6 +11,10 @@ #include "inter.h" #include "int_pet.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + char pet_txt[1024]="save/pet.txt"; #ifndef TXT_SQL_CONVERT diff --git a/src/char/int_pet.h b/src/char/int_pet.h index 43f354798..9234af109 100644 --- a/src/char/int_pet.h +++ b/src/char/int_pet.h @@ -4,6 +4,8 @@ #ifndef _INT_PET_H_ #define _INT_PET_H_ +struct s_pet; + int inter_pet_init(void); void inter_pet_final(void); int inter_pet_save(void); diff --git a/src/char/int_status.c b/src/char/int_status.c index ea255d507..cc25b1485 100644 --- a/src/char/int_status.c +++ b/src/char/int_status.c @@ -1,13 +1,14 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> - -#include "int_status.h" +#include "../common/mmo.h" #include "../common/db.h" #include "../common/lock.h" #include "../common/malloc.h" #include "../common/showmsg.h" +#include "int_status.h" + +#include <stdio.h> static struct dbt * scdata_db = NULL; //Contains all the status change data in-memory. [Skotlex] char scdata_txt[1024]="save/scdata.txt"; //By [Skotlex] diff --git a/src/char/int_status.h b/src/char/int_status.h index 3ddf08299..3202cd88e 100644 --- a/src/char/int_status.h +++ b/src/char/int_status.h @@ -4,7 +4,7 @@ #ifndef _INT_STATUS_H_ #define _INT_STATUS_H_ -#include "char.h" +struct status_change_data; struct scdata { int account_id, char_id; @@ -14,12 +14,10 @@ struct scdata { extern char scdata_txt[1024]; -#ifdef ENABLE_SC_SAVING -struct scdata *status_search_scdata(int aid, int cid); +struct scdata* status_search_scdata(int aid, int cid); void status_delete_scdata(int aid, int cid); void inter_status_save(void); void status_init(void); void status_final(void); -#endif #endif /* _INT_STATUS_H_ */ diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 3698dc78f..4d933d257 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -1,22 +1,23 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - #include "../common/mmo.h" #include "../common/malloc.h" #include "../common/socket.h" #include "../common/db.h" #include "../common/lock.h" #include "../common/showmsg.h" +#include "../common/utils.h" #include "char.h" #include "inter.h" #include "int_storage.h" #include "int_pet.h" #include "int_guild.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + // ƒtƒ@ƒCƒ‹–¼‚̃fƒtƒHƒ‹ƒg // inter_config_read()‚ÅÄݒ肳‚ê‚é char storage_txt[1024]="save/storage.txt"; diff --git a/src/char/int_storage.h b/src/char/int_storage.h index 976d77034..dbc487c4c 100644 --- a/src/char/int_storage.h +++ b/src/char/int_storage.h @@ -4,13 +4,15 @@ #ifndef _INT_STORAGE_H_ #define _INT_STORAGE_H_ +struct storage; +struct guild_storage; + int inter_storage_init(void); void inter_storage_final(void); int inter_storage_save(void); int inter_guild_storage_save(void); int inter_storage_delete(int account_id); int inter_guild_storage_delete(int guild_id); - int inter_storage_parse_frommap(int fd); extern char storage_txt[1024]; diff --git a/src/char/inter.c b/src/char/inter.c index cadb05f92..721017188 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - #include "../common/db.h" #include "../common/mmo.h" #include "../common/socket.h" @@ -12,7 +8,6 @@ #include "../common/malloc.h" #include "../common/lock.h" #include "../common/showmsg.h" - #include "char.h" #include "inter.h" #include "int_party.h" @@ -22,6 +17,10 @@ #include "int_pet.h" #include "int_homun.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + #define WISDATA_TTL (60*1000) // Existence time of Wisp/page data (60 seconds) // that is the waiting time of answers of all map-servers #define WISDELLIST_MAX 256 // Number of elements of Wisp/page data deletion list diff --git a/src/char/inter.h b/src/char/inter.h index 5a6a0edde..c9843965e 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -4,6 +4,8 @@ #ifndef _INTER_H_ #define _INTER_H_ +struct accreg; + int inter_init_txt(const char *file); void inter_final(void); int inter_save(void); diff --git a/src/char_sql/Makefile b/src/char_sql/Makefile deleted file mode 100644 index 21fd1f339..000000000 --- a/src/char_sql/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -all sql: char-server_sql - -COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ - ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ - ../common/obj/strlib.o ../common/obj/grfio.o \ - ../common/obj/mapindex.o ../common/obj/ers.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 - -char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o itemdb.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -clean: - rm -f *.o ../../char-server_sql GNUmakefile - -# DO NOT DELETE - -char.o: char.c char.h ../common/strlib.h itemdb.h ../common/showmsg.h -inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h ../common/mmo.h char.h ../common/socket.h ../common/showmsg.h -int_party.o: int_party.c int_party.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/timer.h ../common/db.h ../common/showmsg.h -int_guild.o: int_guild.c int_guild.h inter.h ../common/mmo.h char.h ../common/socket.h ../common/db.h ../common/showmsg.h -int_storage.o: int_storage.c int_storage.h char.h itemdb.h ../common/showmsg.h -int_pet.o: int_pet.c int_pet.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h -int_homun.o: int_homun.c int_homun.h inter.h char.h ../common/mmo.h ../common/socket.h ../common/db.h ../common/showmsg.h -itemdb.o: itemdb.c itemdb.h ../common/db.h ../common/mmo.h ../common/showmsg.h diff --git a/src/char_sql/Makefile.in b/src/char_sql/Makefile.in new file mode 100644 index 000000000..b47869208 --- /dev/null +++ b/src/char_sql/Makefile.in @@ -0,0 +1,56 @@ +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ + ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ + ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ + ../common/obj/strlib.o ../common/obj/grfio.o \ + ../common/obj/mapindex.o ../common/obj/ers.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/sql.h + +CHAR_OBJ = char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o int_homun.o + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + CHAR_SERVER_SQL_DEPENDS=$(CHAR_OBJ) $(COMMON_OBJ) +else + CHAR_SERVER_SQL_DEPENDS=needs_mysql +endif + +##################################################################### +.PHONY : all char-server_sql clean help + +all: char-server_sql + +char-server_sql: $(CHAR_SERVER_SQL_DEPENDS) + @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) @LIBS@ @MYSQL_LIBS@ + +clean: + rm -f *.o ../../char-server_sql@EXEEXT@ + +help: + @echo "possible targets are 'char-server_sql' 'all' 'clean' 'help'" + @echo "'char-server_sql' - char 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 + +%.o: %.c + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + +# DO NOT DELETE + +char.o: char.c char.h $(COMMON_H) +inter.o: inter.c inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h $(COMMON_H) +int_party.o: int_party.c int_party.h inter.h $(COMMON_H) +int_guild.o: int_guild.c int_guild.h inter.h $(COMMON_H) +int_storage.o: int_storage.c int_storage.h char.h $(COMMON_H) +int_pet.o: int_pet.c int_pet.h inter.h char.h $(COMMON_H) +int_homun.o: int_homun.c int_homun.h inter.h char.h $(COMMON_H) diff --git a/src/char_sql/char.c b/src/char_sql/char.c index 458f784e8..e2baa3b9e 100644 --- a/src/char_sql/char.c +++ b/src/char_sql/char.c @@ -2,17 +2,21 @@ // For more information, see LICENCE in the main folder #include "../common/cbasetypes.h" +#include "../common/strlib.h" +#include "../common/core.h" +#include "../common/timer.h" #include "../common/mmo.h" #include "../common/db.h" #include "../common/malloc.h" +#include "../common/mapindex.h" #include "../common/showmsg.h" -#include "../common/strlib.h" +#include "../common/socket.h" +#include "../common/version.h" #include "../common/utils.h" - #include "inter.h" #include "int_guild.h" #include "int_homun.h" -#include "itemdb.h" +#include "int_party.h" #include "char.h" #include <sys/types.h> @@ -25,7 +29,6 @@ #endif #include <time.h> #include <signal.h> -#include <fcntl.h> #include <string.h> #include <stdarg.h> #include <stdio.h> @@ -121,7 +124,7 @@ static int max_account_id = DEFAULT_MAX_ACCOUNT_ID, max_char_id = DEFAULT_MAX_CH static int online_check = 1; //If one, it won't let players connect when their account is already registered online and will send the relevant map server a kick user request. [Skotlex] // Advanced subnet check [LuzZza] -struct _subnet { +struct s_subnet { uint32 subnet; uint32 mask; uint32 char_ip; @@ -146,7 +149,6 @@ struct { } auth_fifo[AUTH_FIFO_SIZE]; int auth_fifo_pos = 0; -struct mmo_charstatus char_dat; int char_num, char_max; int max_connect_user = 0; int gm_allow_level = 99; @@ -214,11 +216,8 @@ void set_char_online(int map_id, int char_id, int account_id) struct online_char_data* character; if ( char_id != 99 ) { - sprintf(tmp_sql, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'",char_db,char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); if (max_account_id < account_id || max_char_id < char_id) { //Notify map-server of the new max IDs [Skotlex] @@ -270,20 +269,19 @@ void set_char_offline(int char_id, int account_id) struct online_char_data* character; if ( char_id == 99 ) - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id); - else { + { + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) ) + Sql_ShowDebug(sql_handle); + } + else + { cp = idb_get(char_db_,char_id); inter_guild_CharOffline(char_id, cp?cp->guild_id:-1); if (cp) idb_remove(char_db_,char_id); - sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, char_id); - - if (mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); } if ((character = idb_get(online_char_db, account_id)) != NULL) @@ -358,21 +356,12 @@ void set_all_offline(int id) void set_all_offline_sql(void) { //Set all players to 'OFFLINE' - sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", char_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql, "UPDATE `%s` SET `online` = '0'", guild_member_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql, "UPDATE `%s` SET `connect_member` = '0'", guild_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) ) + Sql_ShowDebug(sql_handle); } //---------------------------------------------------------------------- @@ -398,26 +387,31 @@ void read_gm_account(void) aFree(gm_account); GM_num = 0; - sprintf(tmp_sql, "SELECT `%s`,`%s` FROM `%s` WHERE `%s`>='%d'",login_db_account_id,login_db_level,login_db,login_db_level,lowest_gm_level); - if (mysql_query(&lmysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - lsql_res = mysql_store_result(&lmysql_handle); - if (lsql_res) { - gm_account = (struct gm_account*)aCalloc(sizeof(struct gm_account) * (size_t)mysql_num_rows(lsql_res), 1); - while ((lsql_row = mysql_fetch_row(lsql_res))) { - gm_account[GM_num].account_id = atoi(lsql_row[0]); - gm_account[GM_num].level = atoi(lsql_row[1]); - GM_num++; + 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(sql_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); - mysql_free_result(lsql_res); mapif_send_gmaccounts(); } #endif //TXT_SQL_CONVERT -int compare_item(struct item *a, struct item *b) +int compare_item(const struct item* a, const struct item* b) { if(a->id == b->id && @@ -444,15 +438,15 @@ static void* create_charstatus(DBKey key, va_list args) return cp; } #endif //TXT_SQL_CONVERT -int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ - int i=0,j; + +int mmo_char_tosql(int char_id, struct mmo_charstatus* p) +{ + int i = 0; int count = 0; int diff = 0; - char *tmp_ptr; //Building a single query should be more efficient than running - //multiple queries for each thing about to be saved, right? [Skotlex] char save_status[128]; //For displaying save information. [Skotlex] struct mmo_charstatus *cp; - struct itemtmp mapitem[MAX_GUILD_STORAGE]; + StringBuf buf; if (char_id!=p->char_id) return 0; @@ -462,68 +456,35 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ cp = aCalloc(1, sizeof(struct mmo_charstatus)); #endif + StringBuf_Init(&buf); memset(save_status, 0, sizeof(save_status)); - diff = 0; + //map inventory data - for(i=0;i<MAX_INVENTORY;i++){ - if (!compare_item(&p->inventory[i], &cp->inventory[i])) - diff = 1; - if(p->inventory[i].nameid>0){ - mapitem[count].flag=0; - mapitem[count].id = p->inventory[i].id; - mapitem[count].nameid=p->inventory[i].nameid; - mapitem[count].amount = p->inventory[i].amount; - mapitem[count].equip = p->inventory[i].equip; - mapitem[count].identify = p->inventory[i].identify; - mapitem[count].refine = p->inventory[i].refine; - mapitem[count].attribute = p->inventory[i].attribute; - for (j=0; j<MAX_SLOTS; j++) - mapitem[count].card[j] = p->inventory[i].card[j]; - count++; - } + if( memcmp(p->inventory, cp->inventory, sizeof(p->inventory)) ) + { + memitemdata_to_sql(p->inventory, MAX_INVENTORY, p->char_id, TABLE_INVENTORY); + strcat(save_status, " inventory"); } - //printf("- Save item data to MySQL!\n"); - if (diff) - if (!memitemdata_to_sql(mapitem, count, p->char_id,TABLE_INVENTORY)) - strcat(save_status, " inventory"); - - count = 0; - diff = 0; //map cart data - for(i=0;i<MAX_CART;i++){ - if (!compare_item(&p->cart[i], &cp->cart[i])) - diff = 1; - if(p->cart[i].nameid>0){ - mapitem[count].flag=0; - mapitem[count].id = p->cart[i].id; - mapitem[count].nameid=p->cart[i].nameid; - mapitem[count].amount = p->cart[i].amount; - mapitem[count].equip = p->cart[i].equip; - mapitem[count].identify = p->cart[i].identify; - mapitem[count].refine = p->cart[i].refine; - mapitem[count].attribute = p->cart[i].attribute; - for (j=0; j<MAX_SLOTS; j++) - mapitem[count].card[j] = p->cart[i].card[j]; - count++; - } + if( memcmp(p->cart, cp->cart, sizeof(p->cart)) ) + { + memitemdata_to_sql(p->cart, MAX_CART, p->char_id, TABLE_CART); + strcat(save_status, " cart"); } - if (diff) - if (!memitemdata_to_sql(mapitem, count, p->char_id,TABLE_CART)) - strcat(save_status, " cart"); #ifdef TXT_SQL_CONVERT { //Insert the barebones to then update the rest. - char t_name[NAME_LENGTH*2]; - jstrescapecpy(t_name, p->name); - sprintf(tmp_sql, "REPLACE INTO `%s` (`char_id`, `account_id`, `char_num`, `name`) VALUES ('%d', '%d', '%d', '%s')", - char_db, p->char_id, p->account_id, p->char_num, t_name); - if(mysql_query(&mysql_handle, tmp_sql)) + char esc_name[NAME_LENGTH*2+1]; + + Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`account_id`, `char_num`, `name`) VALUES ('%d', '%d', '%s')", + char_db, p->account_id, p->char_num, esc_name) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else - strcat(save_status, " creation"); + Sql_ShowDebug(sql_handle); + } + + strcat(save_status, " creation"); } #endif @@ -544,11 +505,11 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) ) { //Save status - sprintf(tmp_sql ,"UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," "`base_exp`='%u', `job_exp`='%u', `zeny`='%d'," "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," - "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d'," //[orn] add homun_id (homunculus id) + "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d'" " WHERE `account_id`='%d' AND `char_id` = '%d'", @@ -556,19 +517,15 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ p->base_exp, p->job_exp, p->zeny, p->max_hp, p->hp, p->max_sp, p->sp, p->status_point, p->skill_point, p->str, p->agi, p->vit, p->int_, p->dex, p->luk, - p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, //[orn] add homun_id (homunculus id) + p->option, p->party_id, p->guild_id, p->pet_id, p->hom_id, p->weapon, p->shield, p->head_top, p->head_mid, p->head_bottom, mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, - p->account_id, p->char_id - ); - - if(mysql_query(&mysql_handle, tmp_sql)) + p->account_id, p->char_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else - strcat(save_status, " status"); + Sql_ShowDebug(sql_handle); + } + strcat(save_status, " status"); } //Values that will seldom change (to speed up saving) @@ -581,7 +538,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ (p->fame != cp->fame) ) { - sprintf(tmp_sql ,"UPDATE `%s` SET `class`='%d'," + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d'," "`hair`='%d',`hair_color`='%d',`clothes_color`='%d'," "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d'," "`karma`='%d',`manner`='%d', `fame`='%d'" @@ -590,108 +547,81 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ p->hair, p->hair_color, p->clothes_color, p->partner_id, p->father, p->mother, p->child, p->karma, p->manner, p->fame, - p->account_id, p->char_id - ); - if(mysql_query(&mysql_handle, tmp_sql)) + p->account_id, p->char_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else - strcat(save_status, " status2"); - } - - - diff = 0; + Sql_ShowDebug(sql_handle); + } - for(i=0;i<MAX_MEMOPOINTS;i++){ - if(p->memo_point[i].map == cp->memo_point[i].map && p->memo_point[i].x == cp->memo_point[i].x && p->memo_point[i].y == cp->memo_point[i].y) - continue; - diff = 1; - break; + strcat(save_status, " status2"); } - if (diff) - { //Save memo + //memo points + if( memcmp(p->memo_point, cp->memo_point, sizeof(p->memo_point)) ) + { + char esc_mapname[NAME_LENGTH*2+1]; + //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db, p->char_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) ) + Sql_ShowDebug(sql_handle); //insert here. - tmp_ptr = tmp_sql; - tmp_ptr += sprintf(tmp_ptr, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); - count = 0; - for(i=0;i<MAX_MEMOPOINTS;i++){ - if(p->memo_point[i].map){ - tmp_ptr += sprintf(tmp_ptr,"('%d', '%s', '%d', '%d'),", - char_id, mapindex_id2name(p->memo_point[i].map), p->memo_point[i].x, p->memo_point[i].y); - count++; + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); + for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i ) + { + if( p->memo_point[i].map ) + { + if( count ) + StringBuf_AppendStr(&buf, ","); + Sql_EscapeString(sql_handle, esc_mapname, mapindex_id2name(p->memo_point[i].map)); + StringBuf_Printf(&buf, "('%d', '%s', '%d', '%d')", char_id, esc_mapname, p->memo_point[i].x, p->memo_point[i].y); + ++count; } } - if (count) - { //Dangerous? Only if none of the above sprintf worked. [Skotlex] - tmp_ptr[-1] = '\0'; //Remove the trailing comma. - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else - strcat(save_status, " memo"); - } else //Memo Points cleared (how is this possible?). - strcat(save_status, " memo"); + if( count ) + { + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + } + + strcat(save_status, " memo"); } - diff = 0; - for(i=0;i<MAX_SKILL;i++) { + //FIXME: is this neccessary? [ultramage] + for(i=0;i<MAX_SKILL;i++) if ((p->skill[i].lv != 0) && (p->skill[i].id == 0)) p->skill[i].id = i; // Fix skill tree - if((p->skill[i].id != cp->skill[i].id) || (p->skill[i].lv != cp->skill[i].lv) || - (p->skill[i].flag != cp->skill[i].flag)) - { - diff = 1; - break; - } - } - if (diff) - { //Save skills - + //skills + if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) + { //`skill` (`char_id`, `id`, `lv`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db, p->char_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - tmp_ptr = tmp_sql; - tmp_ptr += sprintf(tmp_ptr,"INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db); - count = 0; + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) ) + Sql_ShowDebug(sql_handle); + + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db); //insert here. - for(i=0;i<MAX_SKILL;i++){ + for( i = 0, count = 0; i < MAX_SKILL; ++i ) + { if(p->skill[i].id && p->skill[i].flag!=1) { - tmp_ptr += sprintf(tmp_ptr,"('%d','%d','%d'),", - char_id, p->skill[i].id, (p->skill[i].flag==0)?p->skill[i].lv:p->skill[i].flag-2); - count++; + if( count ) + StringBuf_AppendStr(&buf, ","); + StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == 0 ? p->skill[i].lv : p->skill[i].flag - 2)); + ++count; } } - - if (count) + if( count ) { - tmp_ptr[-1] = '\0'; //Remove trailing comma. - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else - strcat(save_status, " skills"); - } else //Skills removed (reset?) - strcat(save_status, " skills"); + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + } + + strcat(save_status, " skills"); } + diff = 0; for(i = 0; i < MAX_FRIENDS; i++){ if(p->friends[i].char_id != cp->friends[i].char_id || @@ -702,58 +632,54 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ } if(diff == 1) - { //Save friends - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - tmp_ptr = tmp_sql; - tmp_ptr += sprintf(tmp_ptr, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db); - count = 0; - for(i = 0; i < MAX_FRIENDS; i++){ - if(p->friends[i].char_id > 0) + { //Save friends + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) ) + Sql_ShowDebug(sql_handle); + + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db); + for( i = 0, count = 0; i < MAX_FRIENDS; ++i ) + { + if( p->friends[i].char_id > 0 ) { - tmp_ptr += sprintf(tmp_ptr, "('%d','%d','%d'),", char_id, p->friends[i].account_id, p->friends[i].char_id); + if( count ) + StringBuf_AppendStr(&buf, ","); + StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->friends[i].account_id, p->friends[i].char_id); count++; } } - if (count) + if( count ) { - tmp_ptr[-1] = '\0'; //Remove the last comma. [Skotlex] - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + else strcat(save_status, " friends"); - } else //Friend list cleared. + } + else //Friend list cleared. strcat(save_status, " friends"); - } #ifdef HOTKEY_SAVING // hotkeys - tmp_ptr = tmp_sql; - tmp_ptr += sprintf(tmp_ptr, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db); + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db); diff = 0; for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){ if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey))) { - tmp_ptr += sprintf(tmp_ptr, "('%d','%d','%d','%d','%d'),", char_id, i, p->hotkeys[i].type, p->hotkeys[i].id , p->hotkeys[i].lv); + if( diff ) + StringBuf_AppendStr(&buf, ",");// not the first hotkey + StringBuf_Printf(&buf, "('%d','%u','%u','%u','%u')", char_id, (unsigned int)i, (unsigned int)p->hotkeys[i].type, p->hotkeys[i].id , (unsigned int)p->hotkeys[i].lv); diff = 1; } } if(diff) { - tmp_ptr[-1] = 0; - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else { + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + else strcat(save_status, " hotkeys"); - } } #endif + StringBuf_Destroy(&buf); if (save_status[0]!='\0' && save_log) ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status); #ifndef TXT_SQL_CONVERT @@ -764,129 +690,138 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus *p){ return 0; } -// [Ilpalazzo-sama] -int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id, int tableswitch) +/// Saves an array of 'item' entries into the specified table. +int memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch) { - int i,j, flag, id; - char* tablename; - char selectoption[16]; - char* str_p = tmp_sql; + StringBuf buf; + SqlStmt* stmt; + int i; + int j; + const char* tablename; + const char* selectoption; + struct item item; // temp storage variable + bool* flag; // bit array for inventory matching + bool found; switch (tableswitch) { - case TABLE_INVENTORY: tablename = inventory_db; sprintf(selectoption,"char_id"); break; - case TABLE_CART: tablename = cart_db; sprintf(selectoption,"char_id"); break; - case TABLE_STORAGE: tablename = storage_db; sprintf(selectoption,"account_id"); break; - case TABLE_GUILD_STORAGE: tablename = guild_storage_db; sprintf(selectoption,"guild_id"); break; + case TABLE_INVENTORY: tablename = inventory_db; selectoption = "char_id"; break; + case TABLE_CART: tablename = cart_db; selectoption = "char_id"; break; + case TABLE_STORAGE: tablename = storage_db; selectoption = "account_id"; break; + case TABLE_GUILD_STORAGE: tablename = guild_storage_db; selectoption = "guild_id"; break; default: ShowError("Invalid table name!\n"); return 1; } - //=======================================mysql database data > memory=============================================== - - str_p += sprintf(str_p, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); - for (j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p, ", `card%d`", j); + // The following code compares inventory with current database values + // and performs modification/deletion/insertion only on relevant rows. + // This approach is more complicated than a trivial delete&insert, but + // it significantly reduces cpu load on the database server. - str_p += sprintf(str_p, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, char_id); + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + stmt = SqlStmt_Malloc(sql_handle); + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + || SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + StringBuf_Clear(&buf); return 1; } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - while ((sql_row = mysql_fetch_row(sql_res))) { - flag = 0; - id = atoi(sql_row[0]); - for(i = 0; i < count; i++) { - if(mapitem[i].flag == 1) - continue; - if(mapitem[i].nameid == atoi(sql_row[1]) - && mapitem[i].card[0] == atoi(sql_row[7]) - && mapitem[i].card[2] == atoi(sql_row[9]) - && mapitem[i].card[3] == atoi(sql_row[10]) - ) { //They are the same item. - for (j = 0; j<MAX_SLOTS && mapitem[i].card[j] == atoi(sql_row[7+j]); j++); - if (j == MAX_SLOTS && - mapitem[i].amount == atoi(sql_row[2]) && - mapitem[i].equip == atoi(sql_row[3]) && - mapitem[i].identify == atoi(sql_row[4]) && - mapitem[i].refine == atoi(sql_row[5]) && - mapitem[i].attribute == atoi(sql_row[6])) - { //Do nothing. - } else -//==============================================Memory data > SQL =============================== -#ifndef TXT_SQL_CONVERT - if(!itemdb_isequip(mapitem[i].nameid)) - { //Quick update of stackable items. Update Qty and Equip should be enough, but in case we are also updating identify - sprintf(tmp_sql,"UPDATE `%s` SET `equip`='%d', `identify`='%d', `amount`='%d' WHERE `id`='%d' LIMIT 1", - tablename, mapitem[i].equip, mapitem[i].identify,mapitem[i].amount, id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } else -#endif //TXT_SQL_CONVERT - { //Equipment or Misc item, just update all fields. - str_p = tmp_sql; - str_p += sprintf(str_p,"UPDATE `%s` SET `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d'", - tablename, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, mapitem[i].attribute); - - for(j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p, ", `card%d`=%d", j, mapitem[i].card[j]); - - str_p += sprintf(str_p,", `amount`='%d' WHERE `id`='%d' LIMIT 1", - mapitem[i].amount, id); - - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - flag = mapitem[i].flag = 1; //Item dealt with, - break; //skip to next item in the db. - } - } - if(!flag) { //Item not updated, remove it. - sprintf(tmp_sql,"DELETE from `%s` where `id`='%d'", tablename, id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - } - mysql_free_result(sql_res); - } - for(i = 0; i < count; i++) { - if(!mapitem[i].flag) { - str_p = tmp_sql; - str_p += sprintf(str_p,"INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", - tablename, selectoption); - for(j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p,", `card%d`", j); + SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 3, SQLDT_USHORT, &item.equip, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 4, SQLDT_CHAR, &item.identify, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 5, SQLDT_CHAR, &item.refine, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 6, SQLDT_CHAR, &item.attribute, 0, NULL, NULL); + for( j = 0; j < MAX_SLOTS; ++j ) + SqlStmt_BindColumn(stmt, 7+j, SQLDT_SHORT, &item.card[j], 0, NULL, NULL); + + // bit array indicating which inventory items have already been matched + flag = (bool*) aCallocA(max, sizeof(bool)); + + while( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) + { + bool found = false; + // search for the presence of the item in the char's inventory + for( i = 0; i < max; ++i ) + { + if( flag[i] ) + continue; // this item was matched already, skip it - str_p += sprintf(str_p,") VALUES ( '%d','%d', '%d', '%d', '%d', '%d', '%d'", - char_id, mapitem[i].nameid, mapitem[i].amount, mapitem[i].equip, mapitem[i].identify, mapitem[i].refine, - mapitem[i].attribute); + if( items[i].id == 0 ) + { // to make skipping empty entries faster and to prevent saving them later + flag[i] = true; + continue; + } - for(j=0; j<MAX_SLOTS; j++) - str_p +=sprintf(str_p,", '%d'",mapitem[i].card[j]); - - strcat(tmp_sql, ")"); - if(mysql_query(&mysql_handle, tmp_sql)) + if( compare_item(&items[i], &item) ) + ; // Equal - do nothing. + else { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + // update all fields. + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d'", + tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); + StringBuf_Printf(&buf, ", `amount`='%d' WHERE `id`='%d' LIMIT 1", items[i].amount, item.id); + + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + } + + found = flag[i] = true; //Item dealt with, + break; //skip to next item in the db. + } + if( !found ) + {// Item not present in inventory, remove it. + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d'", tablename, item.id) ) + Sql_ShowDebug(sql_handle); + } + } + SqlStmt_Free(stmt); + + StringBuf_Clear(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`", tablename, selectoption); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_AppendStr(&buf, ") VALUES "); + + found = false; + // insert non-matched items into the db as new items + for( i = 0, found = 0; i < max; ++i ) + { + if( !flag[i] ) + { + if( found ) + StringBuf_AppendStr(&buf, ","); + else + found = true; + + StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d'", + id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); + StringBuf_AppendStr(&buf, ")"); } } + + if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + + StringBuf_Destroy(&buf); + aFree(flag); + return 0; } @@ -894,10 +829,12 @@ int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id, int tab //===================================================================================================== int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything) { - int i,j, n; + int i,j; char t_msg[128] = ""; - char* str_p = tmp_sql; struct mmo_charstatus* cp; + StringBuf buf; + char* data; + size_t len; memset(p, 0, sizeof(struct mmo_charstatus)); @@ -905,80 +842,76 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything if (save_log) ShowInfo("Char load request (%d)\n", char_id); // read char data - sprintf(tmp_sql, "SELECT " + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT " "`char_id`,`account_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`hair`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`" - " FROM `%s` WHERE `char_id` = '%d'", char_db, char_id); - - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - - sql_res = mysql_store_result(&mysql_handle); - if (!sql_res) { - ShowError("Load char failed (%d - table %s).\n", char_id, char_db); + " FROM `%s` WHERE `char_id` = '%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - - sql_row = mysql_fetch_row(sql_res); - if (!sql_row) { //Just how does this happens? [Skotlex] + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + { ShowError("Requested non-existant character id: %d!\n", char_id); - mysql_free_result(sql_res); + Sql_FreeResult(sql_handle); return 0; } p->char_id = char_id; - p->account_id = atoi(sql_row[1]); - p->char_num = atoi(sql_row[2]); - strncpy(p->name, sql_row[3], NAME_LENGTH-1); - p->class_ = atoi(sql_row[4]); - p->base_level = atoi(sql_row[5]); - p->job_level = atoi(sql_row[6]); - p->base_exp = (unsigned int)cap_value(atof(sql_row[7]), 0, UINT_MAX); - p->job_exp = (unsigned int)cap_value(atof(sql_row[8]), 0, UINT_MAX); - p->zeny = atoi(sql_row[9]); - p->str = atoi(sql_row[10]); - p->agi = atoi(sql_row[11]); - p->vit = atoi(sql_row[12]); - p->int_ = atoi(sql_row[13]); - p->dex = atoi(sql_row[14]); - p->luk = atoi(sql_row[15]); - p->max_hp = atoi(sql_row[16]); - p->hp = atoi(sql_row[17]); - p->max_sp = atoi(sql_row[18]); - p->sp = atoi(sql_row[19]); - p->status_point = (unsigned short)cap_value(atoi(sql_row[20]), 0, USHRT_MAX); - p->skill_point = (unsigned short)cap_value(atoi(sql_row[21]), 0, USHRT_MAX); - p->option = atoi(sql_row[22]); - p->karma = atoi(sql_row[23]); - p->manner = atoi(sql_row[24]); - p->party_id = atoi(sql_row[25]); - p->guild_id = atoi(sql_row[26]); - p->pet_id = atoi(sql_row[27]); - p->hom_id = atoi(sql_row[28]); - p->hair = atoi(sql_row[29]); - p->hair_color = atoi(sql_row[30]); - p->clothes_color = atoi(sql_row[31]); - p->weapon = atoi(sql_row[32]); - p->shield = atoi(sql_row[33]); - p->head_top = atoi(sql_row[34]); - p->head_mid = atoi(sql_row[35]); - p->head_bottom = atoi(sql_row[36]); - p->last_point.map = mapindex_name2id(sql_row[37]); p->last_point.x = atoi(sql_row[38]); p->last_point.y = atoi(sql_row[39]); - p->save_point.map = mapindex_name2id(sql_row[40]); p->save_point.x = atoi(sql_row[41]); p->save_point.y = atoi(sql_row[42]); - p->partner_id = atoi(sql_row[43]); - p->father = atoi(sql_row[44]); - p->mother = atoi(sql_row[45]); - p->child = atoi(sql_row[46]); - p->fame = atoi(sql_row[47]); - + //TODO: prepared statement goes here >_> [ultramage] + Sql_GetData(sql_handle, 1, &data, NULL); p->account_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->char_num = atoi(data); + Sql_GetData(sql_handle, 3, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 4, &data, NULL); p->class_ = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); p->base_level = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); p->job_level = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); p->base_exp = (unsigned int)cap_value(strtoul(data,NULL,10), 0, UINT_MAX); + Sql_GetData(sql_handle, 8, &data, NULL); p->job_exp = (unsigned int)cap_value(strtoul(data,NULL,10), 0, UINT_MAX); + Sql_GetData(sql_handle, 9, &data, NULL); p->zeny = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); p->str = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); p->agi = atoi(data); + Sql_GetData(sql_handle, 12, &data, NULL); p->vit = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); p->int_ = atoi(data); + Sql_GetData(sql_handle, 14, &data, NULL); p->dex = atoi(data); + Sql_GetData(sql_handle, 15, &data, NULL); p->luk = atoi(data); + Sql_GetData(sql_handle, 16, &data, NULL); p->max_hp = atoi(data); + Sql_GetData(sql_handle, 17, &data, NULL); p->hp = atoi(data); + Sql_GetData(sql_handle, 18, &data, NULL); p->max_sp = atoi(data); + Sql_GetData(sql_handle, 19, &data, NULL); p->sp = atoi(data); + Sql_GetData(sql_handle, 20, &data, NULL); p->status_point = (unsigned short)cap_value(atoi(data), 0, USHRT_MAX); + Sql_GetData(sql_handle, 21, &data, NULL); p->skill_point = (unsigned short)cap_value(atoi(data), 0, USHRT_MAX); + Sql_GetData(sql_handle, 22, &data, NULL); p->option = atoi(data); + Sql_GetData(sql_handle, 23, &data, NULL); p->karma = atoi(data); + Sql_GetData(sql_handle, 24, &data, NULL); p->manner = atoi(data); + Sql_GetData(sql_handle, 25, &data, NULL); p->party_id = atoi(data); + Sql_GetData(sql_handle, 26, &data, NULL); p->guild_id = atoi(data); + Sql_GetData(sql_handle, 27, &data, NULL); p->pet_id = atoi(data); + Sql_GetData(sql_handle, 28, &data, NULL); p->hom_id = atoi(data); + Sql_GetData(sql_handle, 29, &data, NULL); p->hair = atoi(data); + Sql_GetData(sql_handle, 30, &data, NULL); p->hair_color = atoi(data); + Sql_GetData(sql_handle, 31, &data, NULL); p->clothes_color = atoi(data); + Sql_GetData(sql_handle, 32, &data, NULL); p->weapon = atoi(data); + Sql_GetData(sql_handle, 33, &data, NULL); p->shield = atoi(data); + Sql_GetData(sql_handle, 34, &data, NULL); p->head_top = atoi(data); + Sql_GetData(sql_handle, 35, &data, NULL); p->head_mid = atoi(data); + Sql_GetData(sql_handle, 36, &data, NULL); p->head_bottom = atoi(data); + Sql_GetData(sql_handle, 37, &data, NULL); p->last_point.map = mapindex_name2id(data); + Sql_GetData(sql_handle, 38, &data, NULL); p->last_point.x = atoi(data); + Sql_GetData(sql_handle, 39, &data, NULL); p->last_point.y = atoi(data); + Sql_GetData(sql_handle, 40, &data, NULL); p->save_point.map = mapindex_name2id(data); + Sql_GetData(sql_handle, 41, &data, NULL); p->save_point.x = atoi(data); + Sql_GetData(sql_handle, 42, &data, NULL); p->save_point.y = atoi(data); + Sql_GetData(sql_handle, 43, &data, NULL); p->partner_id = atoi(data); + Sql_GetData(sql_handle, 44, &data, NULL); p->father = atoi(data); + Sql_GetData(sql_handle, 45, &data, NULL); p->mother = atoi(data); + Sql_GetData(sql_handle, 46, &data, NULL); p->child = atoi(data); + Sql_GetData(sql_handle, 47, &data, NULL); p->fame = atoi(data); + //free mysql result. - mysql_free_result(sql_res); + Sql_FreeResult(sql_handle); strcat (t_msg, " status"); if (!load_everything) // For quick selection of data when displaying the char menu @@ -986,149 +919,120 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read memo data //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - sprintf(tmp_sql, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`='%d' ORDER by `memo_id`",memo_db, char_id); // TBR - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`='%d' ORDER by `memo_id`", memo_db, char_id) ) + Sql_ShowDebug(sql_handle); - if (sql_res) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - p->memo_point[i].map = mapindex_name2id(sql_row[0]); - p->memo_point[i].x=atoi(sql_row[1]); - p->memo_point[i].y=atoi(sql_row[2]); - } - mysql_free_result(sql_res); - strcat (t_msg, " memo"); + for( i = 0; i < MAX_MEMOPOINTS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + Sql_GetData(sql_handle, 0, &data, NULL); p->memo_point[i].map = mapindex_name2id(data); + Sql_GetData(sql_handle, 1, &data, NULL); p->memo_point[i].x = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->memo_point[i].y = atoi(data); } + strcat(t_msg, " memo"); //read inventory //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) - str_p += sprintf(str_p, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); - - for (j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p, ", `card%d`", j); - - str_p += sprintf(str_p, " FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id); - - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - p->inventory[i].id = atoi(sql_row[0]); - p->inventory[i].nameid = atoi(sql_row[1]); - p->inventory[i].amount = atoi(sql_row[2]); - p->inventory[i].equip = atoi(sql_row[3]); - p->inventory[i].identify = atoi(sql_row[4]); - p->inventory[i].refine = atoi(sql_row[5]); - p->inventory[i].attribute = atoi(sql_row[6]); - for (j=0; j<MAX_SLOTS; j++) - p->inventory[i].card[j] = atoi(sql_row[7+j]); + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id); + + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_INVENTORY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + Sql_GetData(sql_handle, 0, &data, NULL); p->inventory[i].id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); p->inventory[i].nameid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->inventory[i].amount = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); p->inventory[i].equip = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); p->inventory[i].identify = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); p->inventory[i].refine = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); p->inventory[i].attribute = atoi(data); + for( j = 0; j < MAX_SLOTS; ++j ) + { + Sql_GetData(sql_handle, 7 + j, &data, NULL); p->inventory[i].card[j] = atoi(data); } - mysql_free_result(sql_res); - strcat (t_msg, " inventory"); } + strcat(t_msg, " inventory"); //read cart //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) - str_p = tmp_sql; - str_p += sprintf(str_p, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); - for (j = 0; j < MAX_SLOTS; j++) str_p += sprintf(str_p, ", `card%d`", j); - str_p += sprintf(str_p, " FROM `%s` WHERE `char_id`='%d'", cart_db, char_id); - - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - p->cart[i].id = atoi(sql_row[0]); - p->cart[i].nameid = atoi(sql_row[1]); - p->cart[i].amount = atoi(sql_row[2]); - p->cart[i].equip = atoi(sql_row[3]); - p->cart[i].identify = atoi(sql_row[4]); - p->cart[i].refine = atoi(sql_row[5]); - p->cart[i].attribute = atoi(sql_row[6]); - for(j=0; j<MAX_SLOTS; j++) - p->cart[i].card[j] = atoi(sql_row[7+j]); + StringBuf_Clear(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ", `card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", cart_db, char_id); + + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CART && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + Sql_GetData(sql_handle, 0, &data, NULL); p->cart[i].id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); p->cart[i].nameid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->cart[i].amount = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); p->cart[i].equip = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); p->cart[i].identify = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); p->cart[i].refine = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); p->cart[i].attribute = atoi(data); + for( j = 0; j < MAX_SLOTS; ++j ) + { + Sql_GetData(sql_handle, 7 + j, &data, NULL); p->cart[i].card[j] = atoi(data); } - mysql_free_result(sql_res); - strcat (t_msg, " cart"); } + strcat(t_msg, " cart"); //read skill //`skill` (`char_id`, `id`, `lv`) - sprintf(tmp_sql, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`='%d'",skill_db, char_id); // TBR - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - for(i=0;(sql_row = mysql_fetch_row(sql_res));i++){ - n = atoi(sql_row[0]); - p->skill[n].id = n; //memory!? shit!. - p->skill[n].lv = atoi(sql_row[1]); - } - mysql_free_result(sql_res); - strcat (t_msg, " skills"); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_SKILL && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + int n; + Sql_GetData(sql_handle, 0, &data, NULL); + n = atoi(data); + p->skill[n].id = n; //FIXME: why not use a boolean? + Sql_GetData(sql_handle, 1, &data, NULL); + p->skill[n].lv = atoi(data); } + strcat(t_msg, " skills"); //Friend list //Shamelessly stolen from its_sparky (ie: thanks) and then assimilated by [Skotlex] - sprintf(tmp_sql, "SELECT f.friend_account, f.friend_id, c.name FROM `%s` f LEFT JOIN `%s` c ON f.friend_account=c.account_id AND f.friend_id=c.char_id WHERE f.char_id='%d'", friend_db, char_db, char_id); - - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - sql_res = mysql_store_result(&mysql_handle); - if(sql_res) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT c.name, f.friend_account, f.friend_id FROM `%s` f LEFT JOIN `%s` c ON f.friend_account=c.account_id AND f.friend_id=c.char_id WHERE f.char_id='%d'", friend_db, char_db, char_id) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_FRIENDS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) { - for(i = 0; (sql_row = mysql_fetch_row(sql_res)) && i<MAX_FRIENDS; i++) - { - if(sql_row) { //need to check if we have sql_row before we check if we have sql_row[2] because we don't want a segfault - if(sql_row[2]) { - p->friends[i].account_id = atoi(sql_row[0]); - p->friends[i].char_id = atoi(sql_row[1]); - strncpy(p->friends[i].name, sql_row[2], NAME_LENGTH-1); //The -1 is to avoid losing the ending \0 [Skotlex] - } - } - } - mysql_free_result(sql_res); - strcat (t_msg, " friends"); + // name + Sql_GetData(sql_handle, 0, &data, &len); + if( *data == '\0' ) + continue; + memcpy(p->friends[i].name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 1, &data, NULL); p->friends[i].account_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->friends[i].char_id = atoi(data); } + strcat(t_msg, " friends"); #ifdef HOTKEY_SAVING //Hotkeys - sprintf(tmp_sql, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n", mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__, __LINE__, tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - - if (sql_res) { - while ((sql_row = mysql_fetch_row(sql_res))) { - n = atoi(sql_row[0]); - if( n < 0 || n >= HOTKEY_SAVING) - continue; - p->hotkeys[n].type = atoi(sql_row[1]); - p->hotkeys[n].id = atoi(sql_row[2]); - p->hotkeys[n].lv = atoi(sql_row[3]); - } - mysql_free_result(sql_res); - strcat (t_msg, " hotkeys"); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) ) + Sql_ShowDebug(sql_handle); + while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + int n; + Sql_GetData(sql_handle, 0, &data, NULL); n = atoi(data); + if( n < 0 || n >= HOTKEY_SAVING ) + continue; + Sql_GetData(sql_handle, 1, &data, NULL); p->hotkeys[n].type = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); p->hotkeys[n].id = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); p->hotkeys[n].lv = atoi(data); } + strcat(t_msg, " hotkeys"); #endif if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! + Sql_FreeResult(sql_handle); + StringBuf_Destroy(&buf); cp = idb_ensure(char_db_, char_id, create_charstatus); memcpy(cp, p, sizeof(struct mmo_charstatus)); @@ -1140,8 +1044,7 @@ int mmo_char_sql_init(void) { ShowInfo("Begin Initializing.......\n"); char_db_= db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA, sizeof(int)); - // memory initialize - memset(&char_dat, 0, sizeof(struct mmo_charstatus)); + if(char_per_account == 0){ ShowStatus("Chars per Account: 'Unlimited'.......\n"); }else{ @@ -1168,18 +1071,13 @@ int make_new_char_sql(int fd, unsigned char *dat) { struct char_session_data *sd; char name[NAME_LENGTH]; - char t_name[NAME_LENGTH*2]; + char esc_name[NAME_LENGTH*2+1]; unsigned int i; // Used in for loop and comparing with strlen, safe to be unsigned. [Lance] - int char_id, temp; + int char_id; - strncpy(name, dat, NAME_LENGTH); - name[NAME_LENGTH-1] = '\0'; //Always terminate string. + safestrncpy(name, dat, NAME_LENGTH); normalize_name(name,TRIM_CHARS); //Normalize character name. [Skotlex] - jstrescapecpy(t_name, name); - - // disabled until fixed >.> - // Note: escape characters should be added to jstrescape()! - //mysql_real_escape_string(&mysql_handle, t_name, t_name_temp, sizeof(t_name_temp)); + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); if (!session_isValid(fd) || !(sd = (struct char_session_data*)session[fd]->session_data)) return -2; @@ -1194,22 +1092,14 @@ int make_new_char_sql(int fd, unsigned char *dat) //check for charcount (maxchars) :) if(char_per_account != 0){ - sprintf(tmp_sql, "SELECT `account_id` FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if(sql_res){ - //ok - temp = (int)mysql_num_rows(sql_res); - if(temp >= char_per_account){ - //hehe .. limit exceeded :P - ShowInfo("Create char failed (%d): charlimit exceeded.\n", sd->account_id); - mysql_free_result(sql_res); - return -2; - } - mysql_free_result(sql_res); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) ) + Sql_ShowDebug(sql_handle); + if( Sql_NumRows(sql_handle) >= char_per_account ) + { + //hehe .. limit exceeded :P + ShowInfo("Create char failed (%d): charlimit exceeded.\n", sd->account_id); + Sql_FreeResult(sql_handle); + return -2; } } @@ -1231,14 +1121,10 @@ int make_new_char_sql(int fd, unsigned char *dat) (dat[31] >= 9)) { // hair color (dat[31] can not be negativ) if (log_char) { // char.log to charlog - sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char error", sd->account_id, dat[30], t_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - //query - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + charlog_db,"make new char error", sd->account_id, dat[30], esc_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]) ) + Sql_ShowDebug(sql_handle); } ShowWarning("Create char failed (%d): stats error (bot cheat?!)\n", sd->account_id); return -2; @@ -1249,31 +1135,23 @@ int make_new_char_sql(int fd, unsigned char *dat) if (dat[i] < 1 || dat[i] > 9) { if (log_char) { // char.log to charlog - sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char error", sd->account_id, dat[30], t_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - //query - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + charlog_db, "make new char error", sd->account_id, dat[30], esc_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]) ) + Sql_ShowDebug(sql_handle); } ShowWarning("Create char failed (%d): stats error (bot cheat?!)\n", sd->account_id); - return -2; + return -2; } } // now we know that every stat has proper value but we have to check if str/int agi/luk vit/dex pairs are correct if( ((dat[24]+dat[27]) > 10) || ((dat[25]+dat[29]) > 10) || ((dat[26]+dat[28]) > 10) ) { if (log_char) { // char.log to charlog - sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" - "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char error", sd->account_id, dat[30], t_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - //query - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + charlog_db, "make new char error", sd->account_id, dat[30], esc_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]) ) + Sql_ShowDebug(sql_handle); } ShowWarning("Create char failed (%d): stats error (bot cheat?!)\n", sd->account_id); return -2; @@ -1281,93 +1159,58 @@ int make_new_char_sql(int fd, unsigned char *dat) if (log_char) { // char.log to charlog - sprintf(tmp_sql,"INSERT INTO `%s`(`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - charlog_db,"make new char", sd->account_id, dat[30], t_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); - //query - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + charlog_db, "make new char", sd->account_id, dat[30], esc_name, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]) ) + Sql_ShowDebug(sql_handle); } //printf("make new char %d-%d %s %d, %d, %d, %d, %d, %d - %d, %d\n", // fd, dat[30], dat, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], dat[33], dat[31]); //Check Name (already in use?) - sprintf(tmp_sql, "SELECT 1 FROM `%s` WHERE `name` = '%s'",char_db, t_name); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + { + Sql_ShowDebug(sql_handle); return -2; } - sql_res = mysql_store_result(&mysql_handle); - if(sql_res){ - temp = (int)mysql_num_rows(sql_res); - mysql_free_result(sql_res); - if (temp > 0) { - ShowInfo("Create char failed: charname already in use\n"); - return -1; - } + if( Sql_NumRows(sql_handle) > 0 ) + { + ShowInfo("Create char failed: charname already in use\n"); + return -1; } // check char slot. - sprintf(tmp_sql, "SELECT `account_id`, `char_num` FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d'",char_db, sd->account_id, dat[30]); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - - if(sql_res){ - temp = (int)mysql_num_rows(sql_res); - mysql_free_result(sql_res); - if (temp > 0) { - ShowWarning("Create char failed (%d, slot: %d), slot already in use\n", sd->account_id, dat[30]); - return -2; - } + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_num` FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d'", char_db, sd->account_id, dat[30]) ) + Sql_ShowDebug(sql_handle); + if( Sql_NumRows(sql_handle) > 0 ) + { + ShowWarning("Create char failed (%d, slot: %d), slot already in use\n", sd->account_id, dat[30]); + return -2; } //New Querys [Sirius] //Insert the char to the 'chardb' ^^ - sprintf(tmp_sql, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," - "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" - "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", - char_db, sd->account_id , dat[30] , t_name, start_zeny, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], - (40 * (100 + dat[26])/100) , (40 * (100 + dat[26])/100 ), (11 * (100 + dat[27])/100), (11 * (100 + dat[27])/100), dat[33], dat[31], - mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," + "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" + "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", + char_db, sd->account_id , dat[30] , esc_name, start_zeny, dat[24], dat[25], dat[26], dat[27], dat[28], dat[29], + (40 * (100 + dat[26])/100) , (40 * (100 + dat[26])/100 ), (11 * (100 + dat[27])/100), (11 * (100 + dat[27])/100), dat[33], dat[31], + mapindex_id2name(start_point.map), start_point.x, start_point.y, mapindex_id2name(start_point.map), start_point.x, start_point.y) ) + { + Sql_ShowDebug(sql_handle); return -2; //No, stop the procedure! } //Now we need the charid from sql! - if(mysql_field_count(&mysql_handle) == 0 && - mysql_insert_id(&mysql_handle) > 0) - char_id = (int)mysql_insert_id(&mysql_handle); - else { - //delete the char ..(no trash in DB!) but how is this possible? - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' AND `name` = '%s'", char_db, sd->account_id, dat[30], t_name); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - return -2; //XD end of the (World? :P) .. charcreate (denied) - } + char_id = (int)Sql_LastInsertId(sql_handle); //Give the char the default items //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`) if (start_weapon > 0) { //add Start Weapon (Knife?) - sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_weapon,1,0x02,1); - if (mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_weapon, 1, 0x02, 1) ) + Sql_ShowDebug(sql_handle); } if (start_armor > 0) { //Add default armor (cotton shirt?) - sprintf(tmp_sql,"INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_armor,1,0x10,1); - if (mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `equip`, `identify`) VALUES ('%d', '%d', '%d', '%d', '%d')", inventory_db, char_id, start_armor, 1, 0x10, 1) ) + Sql_ShowDebug(sql_handle); } ShowInfo("Created char: account: %d, char: %d, slot: %d, name: %s\n", sd->account_id, char_id, dat[30], name); @@ -1382,58 +1225,50 @@ int make_new_char_sql(int fd, unsigned char *dat) */ int delete_char_sql(int char_id, int partner_id) { - char char_name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Name needs be escaped. - int account_id, party_id, guild_id, hom_id, char_base_level; - - sprintf(tmp_sql, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id` FROM `%s` WHERE `char_id`='%d'",char_db, char_id); + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; //Name needs be escaped. + int account_id; + int party_id; + int guild_id; + int hom_id; + int base_level; + char* data; + size_t len; - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - sql_res = mysql_store_result(&mysql_handle); - - if(sql_res) - sql_row = mysql_fetch_row(sql_res); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); - if (sql_res == NULL || sql_row == NULL) + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { ShowError("delete_char_sql: Unable to fetch character data, deletion aborted.\n"); - if (sql_res) - mysql_free_result(sql_res); + Sql_FreeResult(sql_handle); return -1; } - strncpy(char_name, sql_row[0], NAME_LENGTH); - char_name[NAME_LENGTH-1] = '\0'; - jstrescapecpy(t_name, char_name); //Escape string for sql use... [Skotlex] - account_id = atoi(sql_row[1]); - party_id = atoi(sql_row[2]); - guild_id = atoi(sql_row[3]); - char_base_level = atoi(sql_row[4]); - hom_id = atoi(sql_row[5]); - mysql_free_result(sql_res); //Let's free this as soon as possible to avoid problems later on. + + Sql_GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH); + Sql_GetData(sql_handle, 1, &data, NULL); account_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); party_id = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); guild_id = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); hom_id = atoi(data); + + Sql_EscapeStringLen(sql_handle, esc_name, data, min(len, NAME_LENGTH)); + Sql_FreeResult(sql_handle); //check for config char del condition [Lupus] - if( ( char_del_level > 0 && char_base_level >= char_del_level ) - || ( char_del_level < 0 && char_base_level <= -char_del_level ) + if( ( char_del_level > 0 && base_level >= char_del_level ) + || ( char_del_level < 0 && base_level <= -char_del_level ) ) { - ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n",char_name,char_base_level); + ShowInfo("Char deletion aborted: %s, BaseLevel: %i\n", name, base_level); return -1; } /* Divorce [Wizputer] */ if (partner_id) { - sprintf(tmp_sql,"UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d'",char_db,partner_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql,"DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND `char_id`='%d'",inventory_db,WEDDING_RING_M,WEDDING_RING_F,partner_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d'", char_db, partner_id) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND `char_id`='%d'", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id) ) + Sql_ShowDebug(sql_handle); } //Make the character leave the party [Skotlex] @@ -1442,36 +1277,41 @@ int delete_char_sql(int char_id, int partner_id) /* delete char's pet */ //Delete the hatched pet if you have one... - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'",pet_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) ) + Sql_ShowDebug(sql_handle); // Komurka's suggested way to clear pets, modified by [Skotlex] (because I always personalize what I do :X) //Removing pets that are in the char's inventory.... { //NOTE: The syntax for multi-table deletes is a bit changed between 4.0 and 4.1 regarding aliases, so we have to consider the version... [Skotlex] //Since we only care about the major and minor version, a double conversion is good enough. (4.1.20 -> 4.10000) - double mysql_version = atof(mysql_get_server_info(&mysql_handle)); - - sprintf(tmp_sql, - "delete FROM `%s` USING `%s` as c LEFT JOIN `%s` as i ON c.char_id = i.char_id, `%s` as p WHERE c.char_id = '%d' AND i.card0 = -256 AND p.pet_id = (i.card1|(i.card2<<2))", - (mysql_version<4.1?pet_db:"p"), char_db, inventory_db, pet_db, char_id); - - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - //Removing pets that are in the char's cart.... - sprintf(tmp_sql, - "delete FROM `%s` USING `%s` as c LEFT JOIN `%s` as i ON c.char_id = i.char_id, `%s` as p WHERE c.char_id = '%d' AND i.card0 = -256 AND p.pet_id = (i.card1|(i.card2<<2))", - (mysql_version<4.1?pet_db:"p"), char_db, cart_db, pet_db, char_id); - - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + //double mysql_version = atof(mysql_get_server_info(&mysql_handle)); + // + //sprintf(tmp_sql, + //"delete FROM `%s` USING `%s` as c LEFT JOIN `%s` as i ON c.char_id = i.char_id, `%s` as p WHERE c.char_id = '%d' AND i.card0 = -256 AND p.pet_id = (i.card1|(i.card2<<2))", + // (mysql_version<4.1?pet_db:"p"), char_db, inventory_db, pet_db, char_id); + // + //if(mysql_query(&mysql_handle, tmp_sql)) { + // ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + // ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + //} + + ////Removing pets that are in the char's cart.... + //sprintf(tmp_sql, + //"delete FROM `%s` USING `%s` as c LEFT JOIN `%s` as i ON c.char_id = i.char_id, `%s` as p WHERE c.char_id = '%d' AND i.card0 = -256 AND p.pet_id = (i.card1|(i.card2<<2))", + // (mysql_version<4.1?pet_db:"p"), char_db, cart_db, pet_db, char_id); + // + //if(mysql_query(&mysql_handle, tmp_sql)) { + // ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); + // ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + //} + + //## TODO double-check the functionality of this query + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE pet_id IN " + "(SELECT card1|card2<<2 FROM `%s` WHERE char_id = '%d' AND card0 = -256" + " UNION" + " SELECT card1|card2<<2 FROM `%s` WHERE char_id = '%d' AND card0 = -256)", + pet_db, inventory_db, char_id, cart_db, char_id) ) + Sql_ShowDebug(sql_handle); } /* remove homunculus */ @@ -1479,126 +1319,68 @@ int delete_char_sql(int char_id, int partner_id) inter_delete_homunculus(hom_id); /* delete char's friends list */ - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d'",friend_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) ) + Sql_ShowDebug(sql_handle); /* delete char from other's friend list */ //NOTE: Won't this cause problems for people who are already online? [Skotlex] - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `friend_id` = '%d'",friend_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) ) + Sql_ShowDebug(sql_handle); #ifdef HOTKEY_SAVING /* delete hotkeys */ - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) ) + Sql_ShowDebug(sql_handle); #endif /* delete inventory */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",inventory_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) ) + Sql_ShowDebug(sql_handle); /* delete cart inventory */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",cart_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) ) + Sql_ShowDebug(sql_handle); /* delete memo areas */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",memo_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) ) + Sql_ShowDebug(sql_handle); /* delete character registry */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + Sql_ShowDebug(sql_handle); /* delete skills */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",skill_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) + Sql_ShowDebug(sql_handle); #ifdef ENABLE_SC_SAVING /* status changes */ - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - scdata_db, account_id, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) ) + Sql_ShowDebug(sql_handle); #endif if (log_char) { - sprintf(tmp_sql,"INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')", - charlog_db, account_id, 0, char_id, t_name); - //query - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')", + charlog_db, account_id, 0, char_id, esc_name) ) + Sql_ShowDebug(sql_handle); } /* delete character */ - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",char_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); /* No need as we used inter_guild_leave [Skotlex] // Also delete info from guildtables. - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `char_id`='%d'",guild_member_db, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", guild_member_db, char_id) ) + Sql_ShowDebug(sql_handle); */ - sprintf(tmp_sql, "SELECT `guild_id` FROM `%s` WHERE `master` = '%s'", guild_db, t_name); - - if (mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } else { - sql_res = mysql_store_result(&mysql_handle); - - if (sql_res == NULL) { - if (mysql_errno(&mysql_handle) != 0) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - return -1; - } else { - int rows = (int)mysql_num_rows(sql_res); - mysql_free_result(sql_res); - if (rows > 0) { - mapif_parse_BreakGuild(0,guild_id); - } - else if (guild_id) //Leave your guild. - inter_guild_leave(guild_id, account_id, char_id); - } - } + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `master` = '%s'", guild_db, esc_name) ) + Sql_ShowDebug(sql_handle); + else if( Sql_NumRows(sql_handle) > 0 ) + mapif_parse_BreakGuild(0,guild_id); + else if( guild_id ) + inter_guild_leave(guild_id, account_id, char_id);// Leave your guild. return 0; } @@ -1674,28 +1456,21 @@ int mmo_char_tobuf(uint8* buf, struct mmo_charstatus* p) int mmo_char_send006b(int fd, struct char_session_data* sd) { int i, j, found_num = 0; + char* data; set_char_online(-1, 99, sd->account_id); //search char. - sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id` = '%d' AND `char_num` < '%d'",char_db, sd->account_id, MAX_CHARS); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - found_num = (int)mysql_num_rows(sql_res); -// ShowInfo("number of chars: %d\n", found_num); - i = 0; - while((sql_row = mysql_fetch_row(sql_res))) { - sd->found_char[i] = atoi(sql_row[0]); - i++; - } - mysql_free_result(sql_res); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id` = '%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + // char_id + Sql_GetData(sql_handle, 0, &data, NULL); + sd->found_char[i] = atoi(data); } - - for(i = found_num; i < MAX_CHARS; i++) + found_num = i; + for( ; i < MAX_CHARS; ++i ) sd->found_char[i] = -1; if (save_log) @@ -1708,6 +1483,7 @@ int mmo_char_send006b(int fd, struct char_session_data* sd) memset(WFIFOP(fd,4), 0, 20); // unknown bytes for(i = 0; i < found_num; i++) { + struct mmo_charstatus char_dat; mmo_char_fromsql(sd->found_char[i], &char_dat, false); j += mmo_char_tobuf(WFIFOP(fd,j), &char_dat); } @@ -1925,71 +1701,65 @@ int parse_fromlogin(int fd) { int acc, sex; unsigned char buf[16]; - MYSQL_RES* sql_res2; acc = RFIFOL(fd,2); sex = RFIFOB(fd,6); - if (acc > 0) { - sprintf(tmp_sql, "SELECT `char_id`,`class`,`skill_point`,`guild_id` FROM `%s` WHERE `account_id` = '%d'",char_db, acc); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( acc > 0 ) + { + int char_id[MAX_CHARS]; + int class_[MAX_CHARS]; + int guild_id[MAX_CHARS]; + int num; + int i; + char* data; + + // get characters + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + // char_id + Sql_GetData(sql_handle, 0, &data, NULL); + char_id[i] = atoi(data); + // class + Sql_GetData(sql_handle, 1, &data, NULL); + class_[i] = atoi(data); + // guild_id + Sql_GetData(sql_handle, 2, &data, NULL); + guild_id[i] = atoi(data); } - sql_res2 = mysql_store_result(&mysql_handle); - - while(sql_res2 && (sql_row = mysql_fetch_row(sql_res2))) { - int char_id, guild_id, jobclass, skill_point, class_; - char_id = atoi(sql_row[0]); - jobclass = atoi(sql_row[1]); - skill_point = atoi(sql_row[2]); - guild_id = atoi(sql_row[3]); - class_ = jobclass; - if (jobclass == JOB_BARD || jobclass == JOB_DANCER || - jobclass == JOB_CLOWN || jobclass == JOB_GYPSY || - jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { + num = i; + for( i = 0; i < num; ++i ) + { + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || + class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || + class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) + { // job modification - if (jobclass == JOB_BARD || jobclass == JOB_DANCER) { - class_ = (sex) ? JOB_BARD : JOB_DANCER; - } else if (jobclass == JOB_CLOWN || jobclass == JOB_GYPSY) { - class_ = (sex) ? JOB_CLOWN : JOB_GYPSY; - } else if (jobclass == JOB_BABY_BARD || jobclass == JOB_BABY_DANCER) { - class_ = (sex) ? JOB_BABY_BARD : JOB_BABY_DANCER; - } + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) + class_[i] = (sex ? JOB_BARD : JOB_DANCER); + else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) + class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); + else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) + class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); // remove specifical skills of classes 19,20 4020,4021 and 4042,4043 - sprintf(tmp_sql, "SELECT `lv` FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - while(( sql_row = mysql_fetch_row(sql_res))) { - skill_point += atoi(sql_row[0]); - } - mysql_free_result(sql_res); - } - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'",skill_db, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `skill_point` = `skill_point` +" + " (SELECT SUM(lv) FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330' AND `lv` > '0')" + " WHERE `char_id` = '%d'", + char_db, skill_db, char_id[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' AND `id` >= '315' AND `id` <= '330'", skill_db, char_id[i]) ) + Sql_ShowDebug(sql_handle); } // to avoid any problem with equipment and invalid sex, equipment is unequiped. - sprintf(tmp_sql, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'",inventory_db, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql, "UPDATE `%s` SET `class`='%d' , `skill_point`='%d' , `weapon`='0' , `shield`='0' , `head_top`='0' , `head_mid`='0' , `head_bottom`='0' WHERE `char_id` = '%d'",char_db, class_, skill_point, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - if (guild_id) //If there is a guild, update the guild_member data [Skotlex] - inter_guild_sex_changed(guild_id, acc, char_id, sex); - } - if (sql_res2) - mysql_free_result(sql_res2); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `equip` = '0' WHERE `char_id` = '%d'", inventory_db, char_id[i]) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); + + if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] + inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); + } + Sql_FreeResult(sql_handle); } // disconnect player if online on char-server for(i = 0; i < fd_max; i++) { @@ -2220,74 +1990,59 @@ int save_accreg2(unsigned char* buf, int len) void char_read_fame_list(void) { int i; - struct fame_list fame_item; + char* data; + size_t len; // Empty ranking lists memset(smith_fame_list, 0, sizeof(smith_fame_list)); memset(chemist_fame_list, 0, sizeof(chemist_fame_list)); memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list)); // Build Blacksmith ranking list - sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, fame_list_size_smith); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - i = 0; - while((sql_row = mysql_fetch_row(sql_res))) { - fame_item.id = atoi(sql_row[0]); - fame_item.fame = atoi(sql_row[1]); - strncpy(fame_item.name, sql_row[2], NAME_LENGTH); - memcpy(&smith_fame_list[i], &fame_item, sizeof(struct fame_list)); - - if (++i == fame_list_size_smith) - break; - } - mysql_free_result(sql_res); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, fame_list_size_smith) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + // char_id + Sql_GetData(sql_handle, 0, &data, NULL); + smith_fame_list[i].id = atoi(data); + // fame + Sql_GetData(sql_handle, 1, &data, &len); + smith_fame_list[i].fame = atoi(data); + // name + Sql_GetData(sql_handle, 2, &data, &len); + memcpy(smith_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Alchemist ranking list - sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, fame_list_size_chemist); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - i = 0; - while((sql_row = mysql_fetch_row(sql_res))) { - fame_item.id = atoi(sql_row[0]); - fame_item.fame = atoi(sql_row[1]); - strncpy(fame_item.name, sql_row[2], NAME_LENGTH); - - memcpy(&chemist_fame_list[i], &fame_item, sizeof(struct fame_list)); - - if (++i == fame_list_size_chemist) - break; - } - mysql_free_result(sql_res); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, fame_list_size_chemist) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + // char_id + Sql_GetData(sql_handle, 0, &data, NULL); + chemist_fame_list[i].id = atoi(data); + // fame + Sql_GetData(sql_handle, 1, &data, &len); + chemist_fame_list[i].fame = atoi(data); + // name + Sql_GetData(sql_handle, 2, &data, &len); + memcpy(chemist_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Taekwon ranking list - sprintf(tmp_sql, "SELECT `char_id`,`fame`, `name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - i = 0; - while((sql_row = mysql_fetch_row(sql_res))) { - fame_item.id = atoi(sql_row[0]); - fame_item.fame = atoi(sql_row[1]); - strncpy(fame_item.name, sql_row[2], NAME_LENGTH); - - memcpy(&taekwon_fame_list[i], &fame_item, sizeof(struct fame_list)); - - if (++i == fame_list_size_taekwon) - break; - } - mysql_free_result(sql_res); - } + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + // char_id + Sql_GetData(sql_handle, 0, &data, NULL); + taekwon_fame_list[i].id = atoi(data); + // fame + Sql_GetData(sql_handle, 1, &data, &len); + taekwon_fame_list[i].fame = atoi(data); + // name + Sql_GetData(sql_handle, 2, &data, &len); + memcpy(taekwon_fame_list[i].name, data, min(len, NAME_LENGTH)); + } + Sql_FreeResult(sql_handle); } // Send map-servers the fame ranking lists @@ -2340,22 +2095,23 @@ void char_update_fame_list(int type, int index, int fame) //Returns 1 on found, 0 on not found (buffer is filled with Unknown char name) int char_loadName(int char_id, char* name) { - sprintf(tmp_sql, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - sql_res = mysql_store_result(&mysql_handle); - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; + char* data; + size_t len; - if (sql_row) - memcpy(name, sql_row[0], NAME_LENGTH); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + Sql_GetData(sql_handle, 0, &data, &len); + memset(name, 0, NAME_LENGTH); + memcpy(name, data, min(len, NAME_LENGTH)); + return 1; + } else + { memcpy(name, unknown_char_name, NAME_LENGTH); - if (sql_res) mysql_free_result(sql_res); - - return (sql_row) ? 1 : 0; + } + return 0; } int search_mapserver(unsigned short map, uint32 ip, uint16 port); @@ -2393,11 +2149,8 @@ int parse_frommap(int fd) mapif_sendallwos(fd, buf, WBUFW(buf,2)); } memset(&server[id], 0, sizeof(struct mmo_map_server)); - sprintf(tmp_sql, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo` WHERE `index`='%d'", server_fd[id]) ) + Sql_ShowDebug(sql_handle); server_fd[id] = -1; online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. } @@ -2495,35 +2248,34 @@ int parse_frommap(int fd) int aid, cid; aid = RFIFOL(fd,2); cid = RFIFOL(fd,6); - sprintf(tmp_sql, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - scdata_db, aid, cid); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", + scdata_db, aid, cid) ) + { + Sql_ShowDebug(sql_handle); break; } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - struct status_change_data data; - int count = 0; + if( Sql_NumRows(sql_handle) > 0 ) + { + struct status_change_data scdata; + int count; + char* data; + WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); WFIFOW(fd,0) = 0x2b1d; WFIFOL(fd,4) = aid; WFIFOL(fd,8) = cid; - while((sql_row = mysql_fetch_row(sql_res)) && count < 50) + for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) { - data.type = atoi(sql_row[0]); - data.tick = atoi(sql_row[1]); - data.val1 = atoi(sql_row[2]); - data.val2 = atoi(sql_row[3]); - data.val3 = atoi(sql_row[4]); - data.val4 = atoi(sql_row[5]); - memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &data, sizeof(struct status_change_data)); - count++; + Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); + memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); } if (count >= 50) ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); - mysql_free_result(sql_res); if (count > 0) { WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); @@ -2531,13 +2283,11 @@ int parse_frommap(int fd) WFIFOSET(fd,WFIFOW(fd,2)); //Clear the data once loaded. - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid) ) + Sql_ShowDebug(sql_handle); } } + Sql_FreeResult(sql_handle); #endif RFIFOSKIP(fd, 10); } @@ -2598,6 +2348,7 @@ int parse_frommap(int fd) (character = idb_get(online_char_db, aid)) != NULL && character->char_id == cid)) { + struct mmo_charstatus char_dat; memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); mmo_char_tosql(cid, &char_dat); } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. @@ -2648,6 +2399,7 @@ int parse_frommap(int fd) int map_id, map_fd = -1; struct online_char_data* data; struct mmo_charstatus* char_data; + struct mmo_charstatus char_dat; map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. if (map_id >= 0) @@ -2677,7 +2429,8 @@ int parse_frommap(int fd) WFIFOL(map_fd,12) = (unsigned long)0; //TODO: connect_until_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)); - data = idb_ensure(online_char_db, RFIFOL(fd, 2), create_online_char_data); + + data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); data->char_id = char_data->char_id; data->server = map_id; //Update server where char is. @@ -2739,110 +2492,117 @@ int parse_frommap(int fd) if (RFIFOREST(fd) < 44) return 0; { - char character_name[NAME_LENGTH], t_name[NAME_LENGTH*2]; + char character_name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1];// escaped character name int acc = RFIFOL(fd,2); // account_id of who ask (-1 if nobody) + memcpy(character_name, RFIFOP(fd,6), NAME_LENGTH); character_name[NAME_LENGTH-1] = '\0'; - jstrescapecpy(t_name, character_name); //Escape string for sql use... [Skotlex] + Sql_EscapeStringLen(sql_handle, esc_name, character_name, strnlen(character_name, NAME_LENGTH)); // prepare answer WFIFOHEAD(fd,34); WFIFOW(fd,0) = 0x2b0f; // answer WFIFOL(fd,2) = acc; // who want do operation WFIFOW(fd,30) = RFIFOW(fd, 30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban - sprintf(tmp_sql, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'",char_db, t_name); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + Sql_ShowDebug(sql_handle); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( Sql_NumRows(sql_handle) > 0 ) + { + char* data; + size_t len; - sql_res = mysql_store_result(&mysql_handle); - - if (sql_res) { - if (mysql_num_rows(sql_res)) { - sql_row = mysql_fetch_row(sql_res); - memcpy(WFIFOP(fd,6), sql_row[1], NAME_LENGTH); // put correct name if found - WFIFOW(fd,32) = 0; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - switch(RFIFOW(fd, 30)) { - case 1: // block - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOL(login_fd,6) = 5; // status of the account - WFIFOSET(login_fd,10); - } else - WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + // name + Sql_GetData(sql_handle, 1, &data, &len); + if( len >= NAME_LENGTH ) + memcpy(WFIFOP(fd,6), data, NAME_LENGTH); + else + { + memcpy(WFIFOP(fd,6), data, len); + memset(WFIFOP(fd,6+len), 0, NAME_LENGTH - len); + } + // account_id + Sql_GetData(sql_handle, 0, &data, NULL); + WFIFOW(fd,32) = 0; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + switch(RFIFOW(fd, 30)) { + case 1: // block + if (acc == -1 || isGM(acc) >= isGM(atoi(data))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = atoi(data); // account value + WFIFOL(login_fd,6) = 5; // status of the account + WFIFOSET(login_fd,10); } else - WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 2: // ban - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,18); - WFIFOW(login_fd, 0) = 0x2725; - WFIFOL(login_fd, 2) = atoi(sql_row[0]); // account value - WFIFOW(login_fd, 6) = RFIFOW(fd,32); // year - WFIFOW(login_fd, 8) = RFIFOW(fd,34); // month - WFIFOW(login_fd,10) = RFIFOW(fd,36); // day - WFIFOW(login_fd,12) = RFIFOW(fd,38); // hour - WFIFOW(login_fd,14) = RFIFOW(fd,40); // minute - WFIFOW(login_fd,16) = RFIFOW(fd,42); // second - WFIFOSET(login_fd,18); - } else - WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } else + WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 2: // ban + if (acc == -1 || isGM(acc) >= isGM(atoi(data))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,18); + WFIFOW(login_fd, 0) = 0x2725; + WFIFOL(login_fd, 2) = atoi(data); // account value + WFIFOW(login_fd, 6) = RFIFOW(fd,32); // year + WFIFOW(login_fd, 8) = RFIFOW(fd,34); // month + WFIFOW(login_fd,10) = RFIFOW(fd,36); // day + WFIFOW(login_fd,12) = RFIFOW(fd,38); // hour + WFIFOW(login_fd,14) = RFIFOW(fd,40); // minute + WFIFOW(login_fd,16) = RFIFOW(fd,42); // second + WFIFOSET(login_fd,18); } else - WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 3: // unblock - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOL(login_fd,6) = 0; // status of the account - WFIFOSET(login_fd,10); - } else - WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } else + WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 3: // unblock + if (acc == -1 || isGM(acc) >= isGM(atoi(data))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = atoi(data); // account value + WFIFOL(login_fd,6) = 0; // status of the account + WFIFOSET(login_fd,10); } else - WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 4: // unban - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272a; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOSET(login_fd,6); - } else - WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } else + WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 4: // unban + if (acc == -1 || isGM(acc) >= isGM(atoi(data))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x272a; + WFIFOL(login_fd,2) = atoi(data); // account value + WFIFOSET(login_fd,6); } else - WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - case 5: // changesex - if (acc == -1 || isGM(acc) >= isGM(atoi(sql_row[0]))) { - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2727; - WFIFOL(login_fd,2) = atoi(sql_row[0]); // account value - WFIFOSET(login_fd,6); - } else - WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } else + WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + break; + case 5: // changesex + if (acc == -1 || isGM(acc) >= isGM(atoi(data))) { + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2727; + WFIFOL(login_fd,2) = atoi(data); // account value + WFIFOSET(login_fd,6); } else - WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - break; - } - } else { - // character name not found - memcpy(WFIFOP(fd,6), character_name, NAME_LENGTH); - WFIFOW(fd,32) = 1; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - } - // send answer if a player ask, not if the server ask - if (acc != -1) { - WFIFOSET(fd, 34); + WFIFOW(fd,32) = 3; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } else + WFIFOW(fd,32) = 2; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + break; } - mysql_free_result(sql_res); + } else { + // character name not found + memcpy(WFIFOP(fd,6), character_name, NAME_LENGTH); + WFIFOW(fd,32) = 1; // answer: 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + } + Sql_FreeResult(sql_handle); + // send answer if a player ask, not if the server ask + if (acc != -1) { + WFIFOSET(fd, 34); } RFIFOSKIP(fd, 44); @@ -2908,18 +2668,18 @@ int parse_frommap(int fd) if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,8)) return 0; { - char motd[256], t_name[2*sizeof(char)*sizeof(server_name)+1], t_motd[512]; //Required for jstrescapecpy [Skotlex] + char motd[256]; + char esc_motd[sizeof(motd)*2+1]; + char esc_server_name[sizeof(server_name)*2+1]; + strncpy(motd, RFIFOP(fd,10), 255); //First copy it to make sure the motd fits. - motd[255]='\0'; - jstrescapecpy(t_motd,motd); - jstrescapecpy(t_name,server_name); - - sprintf(tmp_sql, "INSERT INTO `ragsrvinfo` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d',`motd`='%s'", - fd, t_name, RFIFOW(fd,2), RFIFOW(fd,4), RFIFOW(fd,6), t_motd); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + motd[255] = '\0'; + Sql_EscapeString(sql_handle, esc_motd, motd); + Sql_EscapeString(sql_handle, esc_server_name, server_name); + + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `ragsrvinfo` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d',`motd`='%s'", + fd, esc_server_name, RFIFOW(fd,2), RFIFOW(fd,4), RFIFOW(fd,6), esc_motd) ) + Sql_ShowDebug(sql_handle); RFIFOSKIP(fd,RFIFOW(fd,8)); } break; @@ -2956,29 +2716,31 @@ int parse_frommap(int fd) return 0; { #ifdef ENABLE_SC_SAVING - int count, aid, cid, i; - struct status_change_data data; - char *p = tmp_sql; + int count, aid, cid; aid = RFIFOL(fd, 4); cid = RFIFOL(fd, 8); count = RFIFOW(fd, 12); - - p+= sprintf(p, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); - - for (i = 0; i < count; i++) - { - memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); - p += sprintf (p, " ('%d','%d','%hu','%d','%d','%d','%d','%d'),", aid, cid, - data.type, data.tick, data.val1, data.val2, data.val3, data.val4); - } - if (count > 0) + + if( count > 0 ) { - *--p = '\0'; //Remove final comma. - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + struct status_change_data data; + StringBuf buf; + int i; + + StringBuf_Init(&buf); + StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); + for( i = 0; i < count; ++i ) + { + memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); + if( count > 0 ) + StringBuf_AppendStr(&buf, ", "); + StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid, + data.type, data.tick, data.val1, data.val2, data.val3, data.val4); } + if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + StringBuf_Destroy(&buf); } #endif RFIFOSKIP(fd, RFIFOW(fd, 2)); @@ -3156,36 +2918,35 @@ int parse_char(int fd) case 0x66: // char select FIFOSD_CHECK(3); - sprintf(tmp_sql, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'",char_db, sd->account_id, RFIFOB(fd, 2)); - RFIFOSKIP(fd, 3); + do // TODO: poor code structure + { + struct mmo_charstatus char_dat; + char* data; + int char_id; - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; - - if (sql_row) + if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, RFIFOB(fd,2)) + || SQL_SUCCESS != Sql_NextRow(sql_handle) + || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) ) { - int char_id = atoi(sql_row[0]); - mysql_free_result(sql_res); //Free'd as soon as possible - mmo_char_fromsql(char_id, &char_dat, true); - char_dat.sex = sd->sex; - } else { - mysql_free_result(sql_res); + //Not found?? May be forged packet. + Sql_ShowDebug(sql_handle); + Sql_FreeResult(sql_handle); + //TODO: perhaps add some reply? (otherwise it hangs the client) break; } + char_id = atoi(data); + Sql_FreeResult(sql_handle); + mmo_char_fromsql(char_id, &char_dat, true); + char_dat.sex = sd->sex; + if (log_char) { - char escaped_name[NAME_LENGTH*2]; - sprintf(tmp_sql,"INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", - charlog_db, sd->account_id, RFIFOB(fd, 2), jstrescapecpy(escaped_name, char_dat.name)); - //query - if(mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + char esc_name[NAME_LENGTH*2+1]; + + Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", + charlog_db, sd->account_id, RFIFOB(fd, 2), esc_name) ) + Sql_ShowDebug(sql_handle); } ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, RFIFOB(fd, 2), char_dat.name); @@ -3250,6 +3011,22 @@ int parse_char(int fd) WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] WFIFOSET(fd,28); } + { + //Send player to map + uint32 subnet_map_ip; + char map_name[MAP_NAME_LENGTH_EXT]; + snprintf(map_name, MAP_NAME_LENGTH_EXT, "%s.gat", mapindex_id2name(char_dat.last_point.map)); + WFIFOHEAD(fd,28); + WFIFOW(fd,0) = 0x71; + WFIFOL(fd,2) = char_dat.char_id; + memcpy(WFIFOP(fd,6), map_name, MAP_NAME_LENGTH_EXT); + + // 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 [!] + WFIFOSET(fd,28); + } if (auth_fifo_pos >= AUTH_FIFO_SIZE) auth_fifo_pos = 0; auth_fifo[auth_fifo_pos].account_id = sd->account_id; @@ -3273,7 +3050,8 @@ int parse_char(int fd) WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); break; - } + } + //Send auth ok to map server WFIFOHEAD(map_fd,20 + sizeof(struct mmo_charstatus)); WFIFOW(map_fd,0) = 0x2afd; @@ -3284,9 +3062,11 @@ int parse_char(int fd) WFIFOL(map_fd,12) = (unsigned long)auth_fifo[auth_fifo_pos].connect_until_time; memcpy(WFIFOP(map_fd,20), &char_dat, sizeof(struct mmo_charstatus)); WFIFOSET(map_fd, WFIFOW(map_fd,2)); - + set_char_online(i, auth_fifo[auth_fifo_pos].char_id, auth_fifo[auth_fifo_pos].account_id); auth_fifo_pos++; + } while(0); + RFIFOSKIP(fd,3); break; case 0x67: // make new @@ -3313,14 +3093,13 @@ int parse_char(int fd) } { //Send to player. int len; + struct mmo_charstatus char_dat; WFIFOHEAD(fd,110); WFIFOW(fd,0) = 0x6d; mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed. len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat); WFIFOSET(fd,len); - RFIFOSKIP(fd,37); - } //to do for(ch = 0; ch < MAX_CHARS; ch++) { if (sd->found_char[ch] == -1) { @@ -3328,6 +3107,9 @@ int parse_char(int fd) break; } } + + RFIFOSKIP(fd,37); + } break; case 0x68: // delete char @@ -3336,8 +3118,10 @@ int parse_char(int fd) if (cmd == 0x1fb) FIFOSD_CHECK(56); { int cid = RFIFOL(fd,2); + int char_pid=0; - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + WFIFOHEAD(fd,46); + ShowInfo(CL_RED" Request Char Deletion:"CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); memcpy(email, RFIFOP(fd,6), 40); RFIFOSKIP(fd,RFIFOREST(fd)); // hack to make the other deletion packet work @@ -3371,41 +3155,32 @@ int parse_char(int fd) } /* Grab the partner id */ - sprintf(tmp_sql, "SELECT `partner_id` FROM `%s` WHERE `char_id`='%d'",char_db, cid); - - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - sql_res = mysql_store_result(&mysql_handle); - - if(sql_res) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id`='%d'", char_db, cid) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { - int char_pid=0; - sql_row = mysql_fetch_row(sql_res); - if (sql_row) - char_pid = atoi(sql_row[0]); - mysql_free_result(sql_res); - - /* Delete character and partner (if any) */ - if(delete_char_sql(cid, char_pid)<0){ - //can't delete the char - //either SQL error or can't delete by some CONFIG conditions - //del fail - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - break; - } - if (char_pid != 0) - { /* If there is partner, tell map server to do divorce */ - WBUFW(buf,0) = 0x2b12; - WBUFL(buf,2) = cid; - WBUFL(buf,6) = char_pid; - mapif_sendall(buf,10); - } + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + char_pid = atoi(data); + } + + /* Delete character and partner (if any) */ + if(delete_char_sql(cid, char_pid)<0){ + //can't delete the char + //either SQL error or can't delete by some CONFIG conditions + //del fail + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + break; + } + if (char_pid != 0) + { /* If there is partner, tell map server to do divorce */ + WBUFW(buf,0) = 0x2b12; + WBUFL(buf,2) = cid; + WBUFL(buf,6) = char_pid; + mapif_sendall(buf,10); } /* Char successfully deleted.*/ WFIFOHEAD(fd,2); @@ -3824,15 +3599,6 @@ void sql_config_read(const char* cfgName) #ifndef TXT_SQL_CONVERT else if(!strcmpi(w1,"db_path")) strcpy(db_path,w2); - //Map server option to use SQL item/mob-db or not - else if(!strcmpi(w1,"use_sql_db")==0){ - db_use_sqldbs = config_switch(w2); - ShowStatus("Using SQL dbs: %s\n",w2); - } - else if(!strcmpi(w1,"item_db_db")) - strcpy(item_db_db,w2); - else if(!strcmpi(w1,"item_db2_db")) - strcpy(item_db2_db,w2); #endif //support the import command, just like any other config else if(!strcmpi(w1,"import")) @@ -4005,7 +3771,6 @@ int char_config_read(const char* cfgName) void do_final(void) { ShowInfo("Doing final stage...\n"); - do_final_itemdb(); //check SQL save progress. //wait until save char complete @@ -4017,13 +3782,9 @@ void do_final(void) flush_fifos(); mapindex_final(); - - sprintf(tmp_sql,"DELETE FROM `ragsrvinfo"); - if (mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ragsrvinfo") ) + Sql_ShowDebug(sql_handle); if(gm_account) { aFree(gm_account); @@ -4037,9 +3798,9 @@ void do_final(void) char_db_->destroy(char_db_, NULL); online_char_db->destroy(online_char_db, NULL); - mysql_close(&mysql_handle); - if(char_gm_read) - mysql_close(&lmysql_handle); + Sql_Free(sql_handle); + if( lsql_handle ) + Sql_Free(lsql_handle); ShowInfo("ok! all done...\n"); } @@ -4102,9 +3863,6 @@ int do_init(int argc, char **argv) inter_init_sql((argc > 2) ? argv[2] : inter_cfgName); // inter server ÃʱâÈ ShowInfo("Finished reading the inter-server configuration.\n"); - //Read ItemDB - do_init_itemdb(); - ShowInfo("Initializing char server.\n"); online_char_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); mmo_char_sql_init(); @@ -4158,121 +3916,86 @@ int do_init(int argc, char **argv) //Cleaning the tables for NULL entrys @ startup [Sirius] //Chardb clean ShowInfo("Cleaning the '%s' table...\n", char_db); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `account_id` = '0'", char_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", char_db) ) + Sql_ShowDebug(sql_handle); + //guilddb clean - ShowInfo("Cleaning the '%s' table...\n", guild_db); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - + ShowInfo("Cleaning the '%s' table...\n", guild_db); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db) ) + Sql_ShowDebug(sql_handle); + //guildmemberdb clean ShowInfo("Cleaning the '%s' table...\n", guild_member_db); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db); - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - ShowInfo("End of char server initilization function.\n"); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db) ) + Sql_ShowDebug(sql_handle); - ShowInfo("open port %d.....\n",char_port); - char_fd = make_listen_bind(bind_ip, char_port); + ShowInfo("End of char server initilization function.\n"); ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); return 0; } int char_child(int parent_id, int child_id) { - int tmp_id = 0; - sprintf (tmp_sql, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id); - if (mysql_query (&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + if( child_id == atoi(data) ) + { + Sql_FreeResult(sql_handle); + return 1; + } } - sql_res = mysql_store_result (&mysql_handle); - sql_row = sql_res?mysql_fetch_row (sql_res):NULL; - if (sql_row) - tmp_id = atoi (sql_row[0]); - else - ShowError("CHAR: child Failed!\n"); - if (sql_res) mysql_free_result (sql_res); - if ( tmp_id == child_id ) - return 1; - else - return 0; + Sql_FreeResult(sql_handle); + return 0; } int char_married(int pl1, int pl2) { - int tmp_id = 0; - sprintf (tmp_sql, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1); - if (mysql_query (&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + if( pl2 == atoi(data) ) + { + Sql_FreeResult(sql_handle); + return 1; + } } - sql_res = mysql_store_result (&mysql_handle); - sql_row = sql_res?mysql_fetch_row (sql_res):NULL; - if (sql_row) - tmp_id = atoi (sql_row[0]); - else - ShowError("CHAR: married Failed!\n"); - if (sql_res) mysql_free_result (sql_res); - if ( tmp_id == pl2 ) - return 1; - else - return 0; + Sql_FreeResult(sql_handle); + return 0; } int char_family(int pl1, int pl2, int pl3) { - int charid, partnerid, childid; - sprintf (tmp_sql, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, pl1, pl2, pl3); - if (mysql_query (&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - sql_res = mysql_store_result (&mysql_handle); - if (!sql_res) return 0; - - while((sql_row = mysql_fetch_row(sql_res))) + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, pl1, pl2, pl3) ) + Sql_ShowDebug(sql_handle); + else while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { - charid = atoi(sql_row[0]); - partnerid = atoi(sql_row[1]); - childid = atoi(sql_row[2]); - if (charid == pl1) { - if ((pl2 == partnerid && pl3 == childid) || - (pl3 == partnerid && pl2 == childid) - ) { - mysql_free_result (sql_res); - return childid; - } - } - if(charid == pl2) { - if ((pl1 == partnerid && pl3 == childid) || - (pl3 == partnerid && pl1 == childid) - ) { - mysql_free_result (sql_res); - return childid; - } - } - if(charid == pl3) { - if ((pl1 == partnerid && pl2 == childid) || - (pl2 == partnerid && pl1 == childid) - ) { - mysql_free_result (sql_res); - return childid; - } + int charid; + int partnerid; + int childid; + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); charid = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); partnerid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); childid = atoi(data); + + if( (pl1 == charid && ((pl2 == partnerid && pl3 == childid ) || (pl2 == childid && pl3 == partnerid))) || + (pl1 == partnerid && ((pl2 == charid && pl3 == childid ) || (pl2 == childid && pl3 == charid ))) || + (pl1 == childid && ((pl2 == charid && pl3 == partnerid) || (pl2 == partnerid && pl3 == charid ))) ) + { + Sql_FreeResult(sql_handle); + return childid; } } - mysql_free_result (sql_res); + Sql_FreeResult(sql_handle); return 0; } diff --git a/src/char_sql/char.h b/src/char_sql/char.h index 5af183033..c99d1e16a 100644 --- a/src/char_sql/char.h +++ b/src/char_sql/char.h @@ -4,37 +4,13 @@ #ifndef _CHAR_SQL_H_ #define _CHAR_SQL_H_ -#include "../common/core.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/mmo.h" -#include "../common/version.h" -#include "../common/db.h" -#include "../common/mapindex.h" - -#include "inter.h" -#include "int_pet.h" -#include "int_guild.h" -#include "int_party.h" -#include "int_storage.h" -#include "itemdb.h" +struct mmo_charstatus; #define START_CHAR_NUM 150000 #define MAX_MAP_SERVERS 30 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000 -struct itemtmp { - int flag;//checked = 1 else 0 - int id; - short nameid; - short amount; - unsigned short equip; - char identify; - char refine; - char attribute; - short card[4]; -}; enum { TABLE_INVENTORY, TABLE_CART, @@ -42,7 +18,7 @@ enum { TABLE_GUILD_STORAGE, }; -int memitemdata_to_sql(struct itemtmp mapitem[], int count, int char_id,int tableswitch); +int memitemdata_to_sql(const struct item items[], int max, int id, int tableswitch); int mapif_sendall(unsigned char *buf,unsigned int len); int mapif_sendallwos(int fd,unsigned char *buf,unsigned int len); diff --git a/src/char_sql/int_guild.c b/src/char_sql/int_guild.c index b72c85ab2..f33f58097 100644 --- a/src/char_sql/int_guild.c +++ b/src/char_sql/int_guild.c @@ -1,10 +1,6 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - #include "../common/mmo.h" #include "../common/cbasetypes.h" #include "../common/strlib.h" @@ -12,9 +8,14 @@ #include "../common/db.h" #include "../common/malloc.h" #include "../common/socket.h" +#include "../common/timer.h" +#include "char.h" #include "inter.h" #include "int_guild.h" -#include "char.h" + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> #define GS_MEMBER_UNMODIFIED 0x00 #define GS_MEMBER_MODIFIED 0x01 @@ -87,18 +88,10 @@ static int guild_save_timer(int tid, unsigned int tick, int id, int data) { int inter_guild_removemember_tosql(int account_id, int char_id) { - sprintf(tmp_sql,"DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql,"UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id) ) + Sql_ShowDebug(sql_handle); return 0; } #endif //TXT_SQL_CONVERT @@ -120,19 +113,11 @@ int inter_guild_tosql(struct guild *g,int flag) // temporary storage for str convertion. They must be twice the size of the // original string to ensure no overflows will occur. [Skotlex] - char t_name[NAME_LENGTH*2], - t_master[NAME_LENGTH*2], - t_mes1[120], - t_mes2[240], - t_member[NAME_LENGTH*2], - t_position[NAME_LENGTH*2], - t_alliance[NAME_LENGTH*2], - t_ename[NAME_LENGTH*2], - t_emes[80], - t_info[240]; - char emblem_data[4096]; + char t_info[256]; + char esc_name[NAME_LENGTH*2+1]; + char esc_master[NAME_LENGTH*2+1]; char new_guild = 0; - int i=0, sql_index; + int i=0; if (g->guild_id<=0 && g->guild_id != -1) return 0; @@ -140,9 +125,9 @@ int inter_guild_tosql(struct guild *g,int flag) ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).",g->guild_id, flag); #endif - jstrescapecpy(t_name, g->name); - - t_info[0]='\0'; + Sql_EscapeStringLen(sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH)); + Sql_EscapeStringLen(sql_handle, esc_master, g->master, strnlen(g->master, NAME_LENGTH)); + *t_info = '\0'; #ifndef TXT_SQL_CONVERT // Insert a new guild the guild @@ -151,27 +136,19 @@ int inter_guild_tosql(struct guild *g,int flag) strcat(t_info, " guild_create"); // Create a new guild - sprintf(tmp_sql,"INSERT INTO `%s` " + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) " "VALUES ('%s', '%s', '%d', '%d', '%d', '%d')", - guild_db,t_name,jstrescapecpy(t_master,g->master),g->guild_lv,g->max_member,g->average_lv,g->member[0].char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) + guild_db, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(sql_handle); if (g->guild_id == -1) return 0; //Failed to create guild! - } + } else - { - //New guild, catch id - if(mysql_field_count(&mysql_handle) == 0 && mysql_insert_id(&mysql_handle) != 0) - { - g->guild_id = (int)mysql_insert_id(&mysql_handle); - new_guild = 1; - } - else - return 0; //Failed to get ID?? + { + g->guild_id = (int)Sql_LastInsertId(sql_handle); + new_guild = 1; } } #else @@ -180,21 +157,15 @@ int inter_guild_tosql(struct guild *g,int flag) { strcat(t_info, " guild_create"); // Since the PK is guild id + master id, a replace will not be enough if we are overwriting data, we need to wipe the previous guild. - sprintf(tmp_sql,"DELETE FROM `%s` where `guild_id` = '%d'", guild_db,g->guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` where `guild_id` = '%d'", guild_db, g->guild_id) ) + Sql_ShowDebug(sql_handle); // Create a new guild - sprintf(tmp_sql,"REPLACE INTO `%s` " + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` " "(`guild_id`,`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) " "VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d')", - guild_db,g->guild_id,t_name,jstrescapecpy(t_master,g->master),g->guild_lv,g->max_member,g->average_lv,g->member[0].char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) + guild_db, g->guild_id, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(sql_handle); return 0; //Failed to create guild. } } @@ -202,51 +173,79 @@ int inter_guild_tosql(struct guild *g,int flag) // If we need an update on an existing guild or more update on the new guild if (((flag & GS_BASIC_MASK) && !new_guild) || ((flag & (GS_BASIC_MASK & ~GS_BASIC)) && new_guild)) { - sql_index = sprintf(tmp_sql,"UPDATE `%s` SET ", guild_db); + StringBuf buf; + bool add_comma = false; + + StringBuf_Init(&buf); + StringBuf_Printf(&buf, "UPDATE `%s` SET ", guild_db); if (flag & GS_EMBLEM) { - char * pData = emblem_data; + char emblem_data[sizeof(g->emblem_data)*2+1]; + char* pData = emblem_data; + strcat(t_info, " emblem"); // Convert emblem_data to hex + //TODO: why not use binary directly? [ultramage] for(i=0; i<g->emblem_len; i++){ *pData++ = dataToHex[(g->emblem_data[i] >> 4) & 0x0F]; *pData++ = dataToHex[g->emblem_data[i] & 0x0F]; } *pData = 0; - sql_index += sprintf(tmp_sql + sql_index,"`emblem_len`=%d,`emblem_id`=%d,`emblem_data`='%s',",g->emblem_len,g->emblem_id,emblem_data); + StringBuf_Printf(&buf, "`emblem_len`=%d, `emblem_id`=%d, `emblem_data`='%s'", g->emblem_len, g->emblem_id, emblem_data); + add_comma = true; } if (flag & GS_BASIC) { strcat(t_info, " basic"); - sql_index += sprintf(tmp_sql + sql_index,"`name`='%s', `master`='%s', `char_id`=%d,",t_name,jstrescapecpy(t_master,g->master),g->member[0].char_id); + if( add_comma ) + StringBuf_AppendStr(&buf, ", "); + else + add_comma = true; + StringBuf_Printf(&buf, "`name`='%s', `master`='%s', `char_id`=%d", esc_name, esc_master, g->member[0].char_id); } if (flag & GS_CONNECT) { strcat(t_info, " connect"); - sql_index += sprintf(tmp_sql + sql_index,"`connect_member`=%d,`average_lv`=%d,",g->connect_member, g->average_lv); + if( add_comma ) + StringBuf_AppendStr(&buf, ", "); + else + add_comma = true; + StringBuf_Printf(&buf, "`connect_member`=%d, `average_lv`=%d", g->connect_member, g->average_lv); } if (flag & GS_MES) { + char esc_mes1[sizeof(g->mes1)*2+1]; + char esc_mes2[sizeof(g->mes2)*2+1]; + strcat(t_info, " mes"); - sql_index += sprintf(tmp_sql + sql_index,"`mes1`='%s',`mes2`='%s',",jstrescapecpy(t_mes1,g->mes1),jstrescapecpy(t_mes2,g->mes2)); + if( add_comma ) + StringBuf_AppendStr(&buf, ", "); + else + add_comma = true; + Sql_EscapeStringLen(sql_handle, esc_mes1, g->mes1, strnlen(g->mes1, sizeof(g->mes1))); + Sql_EscapeStringLen(sql_handle, esc_mes2, g->mes2, strnlen(g->mes2, sizeof(g->mes2))); + StringBuf_Printf(&buf, "`mes1`='%s', `mes2`='%s'", esc_mes1, esc_mes2); } if (flag & GS_LEVEL) { strcat(t_info, " level"); - sql_index += sprintf(tmp_sql + sql_index,"`guild_lv`=%d,`skill_point`=%d,`exp`=%u,`next_exp`=%u,`max_member`=%d,",g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); - } - sprintf(tmp_sql + sql_index -1," WHERE `guild_id`=%d", g->guild_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( add_comma ) + StringBuf_AppendStr(&buf, ", "); + else + add_comma = true; + StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%u, `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); } + StringBuf_Printf(&buf, " WHERE `guild_id`=%d", g->guild_id); + if( SQL_ERROR == Sql_Query(sql_handle, "%s", StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + StringBuf_Destroy(&buf); } if (flag&GS_MEMBER) { struct guild_member *m; + strcat(t_info, " members"); // Update only needed players for(i=0;i<g->max_member;i++){ @@ -257,26 +256,18 @@ int inter_guild_tosql(struct guild *g,int flag) #endif if(m->account_id) { //Since nothing references guild member table as foreign keys, it's safe to use REPLACE INTO - sprintf(tmp_sql,"REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) " + Sql_EscapeStringLen(sql_handle, esc_name, m->name, strnlen(m->name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) " "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%u','%d','%d','%d','%s')", - guild_member_db, g->guild_id, m->account_id,m->char_id, - m->hair,m->hair_color,m->gender, - m->class_,m->lv,m->exp,m->exp_payper,m->online,m->position, - jstrescapecpy(t_member,m->name)); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + guild_member_db, g->guild_id, m->account_id, m->char_id, + m->hair, m->hair_color, m->gender, + m->class_, m->lv, m->exp, m->exp_payper, m->online, m->position, esc_name) ) + Sql_ShowDebug(sql_handle); if (m->modified & GS_MEMBER_NEW) { - sprintf(tmp_sql,"UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'", - char_db, g->guild_id, m->char_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'", + char_db, g->guild_id, m->char_id) ) + Sql_ShowDebug(sql_handle); } m->modified = GS_MEMBER_UNMODIFIED; } @@ -292,13 +283,10 @@ int inter_guild_tosql(struct guild *g,int flag) if (!p->modified) continue; #endif - sprintf(tmp_sql,"REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d', '%s','%d','%d')", - guild_position_db, g->guild_id, i, jstrescapecpy(t_position,p->name),p->mode,p->exp_mode); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d','%s','%d','%d')", + guild_position_db, g->guild_id, i, esc_name, p->mode, p->exp_mode) ) + Sql_ShowDebug(sql_handle); p->modified = GS_POSITION_UNMODIFIED; } } @@ -309,12 +297,10 @@ int inter_guild_tosql(struct guild *g,int flag) // NOTE: no need to do it on both sides since both guilds in memory had // their info changed, not to mention this would also mess up oppositions! // [Skotlex] -// sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'",guild_alliance_db, g->guild_id,g->guild_id); - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_alliance_db, g->guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) + //if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'", guild_alliance_db, g->guild_id, g->guild_id) ) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, g->guild_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(sql_handle); } else { @@ -324,15 +310,11 @@ int inter_guild_tosql(struct guild *g,int flag) struct guild_alliance *a=&g->alliance[i]; if(a->guild_id>0) { - sprintf(tmp_sql,"REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " + Sql_EscapeStringLen(sql_handle, esc_name, a->name, strnlen(a->name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " "VALUES ('%d','%d','%d','%s')", - guild_alliance_db, g->guild_id,a->opposition,a->guild_id,jstrescapecpy(t_alliance,a->name)); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + guild_alliance_db, g->guild_id, a->opposition, a->guild_id, esc_name) ) + Sql_ShowDebug(sql_handle); } } } @@ -344,15 +326,17 @@ int inter_guild_tosql(struct guild *g,int flag) for(i=0;i<MAX_GUILDEXPULSION;i++){ struct guild_expulsion *e=&g->expulsion[i]; if(e->account_id>0){ - sprintf(tmp_sql,"REPLACE INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) " + char esc_mes[sizeof(e->mes)*2+1]; + char esc_acc[sizeof(e->acc)*2+1]; + + Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH)); + Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes))); + Sql_EscapeStringLen(sql_handle, esc_acc, e->acc, strnlen(e->acc, sizeof(e->acc))); + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3`) " "VALUES ('%d','%s','%s','%s','%d','%d','%d','%d')", guild_expulsion_db, g->guild_id, - jstrescapecpy(t_ename,e->name),jstrescapecpy(t_emes,e->mes),e->acc,e->account_id,e->rsv1,e->rsv2,e->rsv3 ); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + esc_name, esc_mes, esc_acc, e->account_id, e->rsv1, e->rsv2 ,e->rsv3) ) + Sql_ShowDebug(sql_handle); } } } @@ -362,13 +346,9 @@ int inter_guild_tosql(struct guild *g,int flag) //printf("- Insert guild %d to guild_skill\n",g->guild_id); for(i=0;i<MAX_GUILDSKILL;i++){ if (g->skill[i].id>0 && g->skill[i].lv>0){ - sprintf(tmp_sql,"REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", - guild_skill_db, g->guild_id,g->skill[i].id,g->skill[i].lv); - //printf("%s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", + guild_skill_db, g->guild_id, g->skill[i].id, g->skill[i].lv) ) + Sql_ShowDebug(sql_handle); } } } @@ -377,213 +357,199 @@ int inter_guild_tosql(struct guild *g,int flag) ShowInfo("Saved guild (%d - %s):%s\n",g->guild_id,g->name,t_info); return 1; } + #ifndef TXT_SQL_CONVERT // Read guild from sql struct guild * inter_guild_fromsql(int guild_id) { - int i; - char * pstr, * pEmblemData; struct guild *g; + char* data; + size_t len; + char* p; + int i; - if (guild_id<=0) return NULL; - - g = idb_get(guild_db_,guild_id); - if (g) return g; + if( guild_id <= 0 ) + return NULL; - g = (struct guild*)aCalloc(sizeof(struct guild), 1); + g = idb_get(guild_db_, guild_id); + if( g ) + return g; #ifdef NOISY ShowInfo("Guild load request (%d)...\n", guild_id); #endif - - sprintf(tmp_sql,"SELECT `name`,`master`,`guild_lv`,`connect_member`,`max_member`,`average_lv`,`exp`,`next_exp`,`skill_point`,`mes1`,`mes2`,`emblem_len`,`emblem_id`,`emblem_data` " - "FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - aFree(g); - return NULL; - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res==NULL || mysql_num_rows(sql_res)<1) { - //Guild does not exists. - if (sql_res) mysql_free_result(sql_res); - aFree(g); - return NULL; - } - - sql_row = mysql_fetch_row(sql_res); - if (sql_row==NULL) { - mysql_free_result(sql_res); - aFree(g); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`master`,`guild_lv`,`connect_member`,`max_member`,`average_lv`,`exp`,`next_exp`,`skill_point`,`mes1`,`mes2`,`emblem_len`,`emblem_id`,`emblem_data` " + "FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); return NULL; } - g->guild_id=guild_id; - strncpy(g->name,sql_row[0],NAME_LENGTH-1); - strncpy(g->master,sql_row[1],NAME_LENGTH-1); - g->guild_lv=atoi(sql_row[2]); - g->connect_member=atoi(sql_row[3]); - g->max_member = atoi(sql_row[4]); - if (g->max_member > MAX_GUILD) + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + return NULL;// Guild does not exists. + + CREATE(g, struct guild, 1); + + g->guild_id = guild_id; + Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data); + if( g->max_member > MAX_GUILD ) { // Fix reduction of MAX_GUILD [PoW] ShowWarning("Guild %d:%s specifies higher capacity (%d) than MAX_GUILD (%d)\n", guild_id, g->name, g->max_member, MAX_GUILD); g->max_member = MAX_GUILD; } - g->average_lv=atoi(sql_row[5]); - g->exp=(unsigned int)atof(sql_row[6]); - g->next_exp=(unsigned int)atof(sql_row[7]); - g->skill_point=atoi(sql_row[8]); - //There shouldn't be a need to copy the very last char, as it's the \0 [Skotlex] - strncpy(g->mes1,sql_row[9],59); - strncpy(g->mes2,sql_row[10],119); - g->emblem_len=atoi(sql_row[11]); - g->emblem_id=atoi(sql_row[12]); - //FIXME: check for sql_row[13]==NULL, just in case - for(i=0,pstr=sql_row[13],pEmblemData=g->emblem_data; i < g->emblem_len; i++,pstr+=2){ - int c1=pstr[0],c2=pstr[1],x1=0,x2=0; - if(c1>='0' && c1<='9') - x1=c1-'0'; - else if(c1>='a' && c1<='f') - x1=c1-'a'+10; - else if(c1>='A' && c1<='F') - x1=c1-'A'+10; - if(c2>='0' && c2<='9') - x2=c2-'0'; - else if(c2>='a' && c2<='f') - x2=c2-'a'+10; - else if(c2>='A' && c2<='F') - x2=c2-'A'+10; - *pEmblemData++=(x1<<4)|x2; + Sql_GetData(sql_handle, 5, &data, NULL); g->average_lv = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); g->exp = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 8, &data, NULL); g->skill_point = atoi(data); + Sql_GetData(sql_handle, 9, &data, &len); memcpy(g->mes1, data, min(len, sizeof(g->mes1))); + Sql_GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, min(len, sizeof(g->mes2))); + Sql_GetData(sql_handle, 11, &data, &len); g->emblem_len = atoi(data); + Sql_GetData(sql_handle, 12, &data, &len); g->emblem_id = atoi(data); + Sql_GetData(sql_handle, 13, &data, &len); + // convert emblem data from hexadecimal to binary + //TODO: why not store it in the db as binary directly? [ultramage] + for( i = 0, p = g->emblem_data; i < g->emblem_len; ++i, ++p ) + { + if( *data >= '0' && *data <= '9' ) + *p = *data - '0'; + else if( *data >= 'a' && *data <= 'f' ) + *p = *data - 'a' + 10; + else if( *data >= 'A' && *data <= 'F' ) + *p = *data - 'A' + 10; + *p <<= 4; + ++data; + + if( *data >= '0' && *data <= '9' ) + *p |= *data - '0'; + else if( *data >= 'a' && *data <= 'f' ) + *p |= *data - 'a' + 10; + else if( *data >= 'A' && *data <= 'F' ) + *p |= *data - 'A' + 10; + ++data; } - mysql_free_result(sql_res); //printf("- Read guild_member %d from sql \n",guild_id); - sprintf(tmp_sql,"SELECT `guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name` " - "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`rsv1`,`rsv2`,`name` " + "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - for(i=0;((sql_row = mysql_fetch_row(sql_res))&&i<g->max_member);i++){ - struct guild_member *m = &g->member[i]; - m->account_id=atoi(sql_row[1]); - m->char_id=atoi(sql_row[2]); - m->hair=atoi(sql_row[3]); - m->hair_color=atoi(sql_row[4]); - m->gender=atoi(sql_row[5]); - m->class_=atoi(sql_row[6]); - m->lv=atoi(sql_row[7]); - m->exp=strtoul(sql_row[8],NULL,10); - m->exp_payper=atoi(sql_row[9]); - m->online=atoi(sql_row[10]); - m->position = atoi(sql_row[11]); - if (m->position >= MAX_GUILDPOSITION) // Fix reduction of MAX_GUILDPOSITION [PoW] - m->position = MAX_GUILDPOSITION - 1; - - strncpy(m->name,sql_row[14],NAME_LENGTH-1); - m->modified = GS_MEMBER_UNMODIFIED; - } - mysql_free_result(sql_res); + for( i = 0; i < g->max_member && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + struct guild_member* m = &g->member[i]; + + Sql_GetData(sql_handle, 1, &data, NULL); m->account_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); m->char_id = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); m->hair = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); m->hair_color = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); m->gender = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); m->lv = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10); + Sql_GetData(sql_handle, 9, &data, NULL); m->exp_payper = (unsigned int)atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); m->online = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); m->position = atoi(data); + if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW] + m->position = MAX_GUILDPOSITION - 1; + //## TODO what about the rsv fields? + // rsv1 (12) + // rsv2 (13) + // name + Sql_GetData(sql_handle, 14, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + m->modified = GS_MEMBER_UNMODIFIED; } //printf("- Read guild_position %d from sql \n",guild_id); - sprintf(tmp_sql,"SELECT `guild_id`,`position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'",guild_position_db, guild_id); - //printf(" %s\n",tmp_sql); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - for(i=0;((sql_row = mysql_fetch_row(sql_res))&&i<MAX_GUILDPOSITION);i++){ - int position = atoi(sql_row[1]); - struct guild_position *p = &g->position[position]; - strncpy(p->name,sql_row[2],NAME_LENGTH-1); - p->mode=atoi(sql_row[3]); - p->exp_mode=atoi(sql_row[4]); - p->modified = GS_POSITION_UNMODIFIED; - } - mysql_free_result(sql_res); + while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + int position; + struct guild_position* p; + + Sql_GetData(sql_handle, 1, &data, NULL); position = atoi(data); + if( position < 0 || position >= MAX_GUILDPOSITION ) + continue;// invalid position + p = &g->position[position]; + Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 3, &data, NULL); p->mode = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); p->exp_mode = atoi(data); + p->modified = GS_POSITION_UNMODIFIED; } //printf("- Read guild_alliance %d from sql \n",guild_id); - sprintf(tmp_sql,"SELECT `guild_id`,`opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'",guild_alliance_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - for(i=0;((sql_row = mysql_fetch_row(sql_res))&&i<MAX_GUILDALLIANCE);i++){ - struct guild_alliance *a = &g->alliance[i]; - a->opposition=atoi(sql_row[1]); - a->guild_id=atoi(sql_row[2]); - strncpy(a->name,sql_row[3],NAME_LENGTH-1); - } - mysql_free_result(sql_res); + for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + struct guild_alliance* a = &g->alliance[i]; + + Sql_GetData(sql_handle, 1, &data, NULL); a->opposition = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); a->guild_id = atoi(data); + Sql_GetData(sql_handle, 3, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH)); } //printf("- Read guild_expulsion %d from sql \n",guild_id); - sprintf(tmp_sql,"SELECT `guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3` FROM `%s` WHERE `guild_id`='%d'",guild_expulsion_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`name`,`mes`,`acc`,`account_id`,`rsv1`,`rsv2`,`rsv3` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - for(i=0;((sql_row = mysql_fetch_row(sql_res))&&i<MAX_GUILDEXPULSION);i++){ - struct guild_expulsion *e = &g->expulsion[i]; - - strncpy(e->name,sql_row[1],NAME_LENGTH-1); - //No need to copy char 40, the null terminator. [Skotlex] - strncpy(e->mes,sql_row[2],39); - strncpy(e->acc,sql_row[3],39); - e->account_id=atoi(sql_row[4]); - e->rsv1=atoi(sql_row[5]); - e->rsv2=atoi(sql_row[6]); - e->rsv3=atoi(sql_row[7]); - } - mysql_free_result(sql_res); + for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + struct guild_expulsion *e = &g->expulsion[i]; + + Sql_GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes))); + Sql_GetData(sql_handle, 3, &data, &len); memcpy(e->acc, data, min(len, sizeof(e->acc))); + Sql_GetData(sql_handle, 4, &data, NULL); e->account_id = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); e->rsv1 = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); e->rsv2 = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); e->rsv3 = atoi(data); } //printf("- Read guild_skill %d from sql \n",guild_id); - sprintf(tmp_sql,"SELECT `guild_id`,`id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`",guild_skill_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id`,`id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) + { + Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - + for(i = 0; i < MAX_GUILDSKILL; i++) { //Skill IDs must always be initialized. [Skotlex] g->skill[i].id = i + GD_SKILLBASE; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - while ((sql_row = mysql_fetch_row(sql_res))){ - int id = atoi(sql_row[1])-GD_SKILLBASE; - if (id >= 0 && id < MAX_GUILDSKILL) - //I know this seems ridiculous, but the skills HAVE to be placed on their 'correct' array slot or things break x.x [Skotlex] - g->skill[id].lv=atoi(sql_row[2]); - } - mysql_free_result(sql_res); - } + while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + int id; + // id + Sql_GetData(sql_handle, 1, &data, NULL); + id = atoi(data) - GD_SKILLBASE; + if( id < 0 && id >= MAX_GUILDSKILL ) + continue;// invalid guild skill + // lv + Sql_GetData(sql_handle, 2, &data, NULL); + g->skill[id].lv = atoi(data); + } + Sql_FreeResult(sql_handle); idb_put(guild_db_, guild_id, g); //Add to cache g->save_flag |= GS_REMOVE; //But set it to be removed, in case it is not needed for long. @@ -604,8 +570,7 @@ ShowDebug("Save guild_castle (%d)\n", gc->castle_id); #endif // sql_query("DELETE FROM `%s` WHERE `castle_id`='%d'",guild_castle_db, gc->castle_id); - - sprintf(tmp_sql,"REPLACE INTO `%s` " + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` " "(`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`," "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`," "`Ghp0`, `Ghp1`, `Ghp2`, `Ghp3`, `Ghp4`, `Ghp5`, `Ghp6`, `Ghp7`)" @@ -613,12 +578,8 @@ ShowDebug("Save guild_castle (%d)\n", gc->castle_id); guild_castle_db, gc->castle_id, gc->guild_id, gc->economy, gc->defense, gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC, gc->guardian[0].visible, gc->guardian[1].visible, gc->guardian[2].visible, gc->guardian[3].visible, gc->guardian[4].visible, gc->guardian[5].visible, gc->guardian[6].visible, gc->guardian[7].visible, - gc->guardian[0].hp, gc->guardian[1].hp, gc->guardian[2].hp, gc->guardian[3].hp, gc->guardian[4].hp, gc->guardian[5].hp, gc->guardian[6].hp, gc->guardian[7].hp); - - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + gc->guardian[0].hp, gc->guardian[1].hp, gc->guardian[2].hp, gc->guardian[3].hp, gc->guardian[4].hp, gc->guardian[5].hp, gc->guardian[6].hp, gc->guardian[7].hp) ) + Sql_ShowDebug(sql_handle); #ifndef TXT_SQL_CONVERT memcpy(&castles[gc->castle_id],gc,sizeof(struct guild_castle)); @@ -631,6 +592,8 @@ ShowDebug("Save guild_castle (%d)\n", gc->castle_id); int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc) { static int castles_init=0; + char* data; + if (gc==NULL) return 0; if (castle_id==-1) return 0; @@ -649,58 +612,54 @@ int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc) } memset(gc,0,sizeof(struct guild_castle)); - sprintf(tmp_sql,"SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, " + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, " "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`," "`Ghp0`, `Ghp1`, `Ghp2`, `Ghp3`, `Ghp4`, `Ghp5`, `Ghp6`, `Ghp7`" - " FROM `%s` WHERE `castle_id`='%d'",guild_castle_db, castle_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + " FROM `%s` WHERE `castle_id`='%d'", guild_castle_db, castle_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } // ARU: This needs to be set even if there are no SQL results gc->castle_id=castle_id; - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { - sql_row = mysql_fetch_row(sql_res); - if (sql_row==NULL){ - mysql_free_result(sql_res); - return 1; //Assume empty castle. - } - gc->guild_id = atoi (sql_row[1]); - gc->economy = atoi (sql_row[2]); - gc->defense = atoi (sql_row[3]); - gc->triggerE = atoi (sql_row[4]); - gc->triggerD = atoi (sql_row[5]); - gc->nextTime = atoi (sql_row[6]); - gc->payTime = atoi (sql_row[7]); - gc->createTime = atoi (sql_row[8]); - gc->visibleC = atoi (sql_row[9]); - gc->guardian[0].visible = atoi (sql_row[10]); - gc->guardian[1].visible = atoi (sql_row[11]); - gc->guardian[2].visible = atoi (sql_row[12]); - gc->guardian[3].visible = atoi (sql_row[13]); - gc->guardian[4].visible = atoi (sql_row[14]); - gc->guardian[5].visible = atoi (sql_row[15]); - gc->guardian[6].visible = atoi (sql_row[16]); - gc->guardian[7].visible = atoi (sql_row[17]); - gc->guardian[0].hp = atoi (sql_row[18]); - gc->guardian[1].hp = atoi (sql_row[19]); - gc->guardian[2].hp = atoi (sql_row[20]); - gc->guardian[3].hp = atoi (sql_row[21]); - gc->guardian[4].hp = atoi (sql_row[22]); - gc->guardian[5].hp = atoi (sql_row[23]); - gc->guardian[6].hp = atoi (sql_row[24]); - gc->guardian[7].hp = atoi (sql_row[25]); - - if (save_log) - ShowInfo("Loaded Castle %d (guild %d)\n",castle_id,gc->guild_id); - - } - mysql_free_result(sql_res) ; //resource free - + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + { + Sql_FreeResult(sql_handle); + return 1; //Assume empty castle. + } + + Sql_GetData(sql_handle, 1, &data, NULL); gc->guild_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); gc->economy = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); gc->defense = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); gc->triggerE = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); gc->triggerD = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); gc->nextTime = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); gc->payTime = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); gc->createTime = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); gc->visibleC = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); gc->guardian[0].visible = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); gc->guardian[1].visible = atoi(data); + Sql_GetData(sql_handle, 12, &data, NULL); gc->guardian[2].visible = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); gc->guardian[3].visible = atoi(data); + Sql_GetData(sql_handle, 14, &data, NULL); gc->guardian[4].visible = atoi(data); + Sql_GetData(sql_handle, 15, &data, NULL); gc->guardian[5].visible = atoi(data); + Sql_GetData(sql_handle, 16, &data, NULL); gc->guardian[6].visible = atoi(data); + Sql_GetData(sql_handle, 17, &data, NULL); gc->guardian[7].visible = atoi(data); + Sql_GetData(sql_handle, 18, &data, NULL); gc->guardian[0].hp = atoi(data); + Sql_GetData(sql_handle, 19, &data, NULL); gc->guardian[1].hp = atoi(data); + Sql_GetData(sql_handle, 20, &data, NULL); gc->guardian[2].hp = atoi(data); + Sql_GetData(sql_handle, 21, &data, NULL); gc->guardian[3].hp = atoi(data); + Sql_GetData(sql_handle, 22, &data, NULL); gc->guardian[4].hp = atoi(data); + Sql_GetData(sql_handle, 23, &data, NULL); gc->guardian[5].hp = atoi(data); + Sql_GetData(sql_handle, 24, &data, NULL); gc->guardian[6].hp = atoi(data); + Sql_GetData(sql_handle, 25, &data, NULL); gc->guardian[7].hp = atoi(data); + + Sql_FreeResult(sql_handle); memcpy(&castles[castle_id],gc,sizeof(struct guild_castle)); + if( save_log ) + ShowInfo("Loaded Castle %d (guild %d)\n", castle_id, gc->guild_id); + return 1; } @@ -740,20 +699,24 @@ int inter_guild_CharOnline(int char_id, int guild_id) { if (guild_id == -1) { //Get guild_id from the database - sprintf (tmp_sql , "SELECT guild_id FROM `%s` WHERE char_id='%d'",char_db,char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if(sql_res == NULL) - return 0; //Eh? No guild? - - sql_row = mysql_fetch_row(sql_res); - guild_id = sql_row?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + guild_id = atoi(data); + } + else + { + guild_id = 0; + } + Sql_FreeResult(sql_handle); } if (guild_id == 0) return 0; //No guild... @@ -785,20 +748,24 @@ int inter_guild_CharOffline(int char_id, int guild_id) { if (guild_id == -1) { //Get guild_id from the database - sprintf (tmp_sql , "SELECT guild_id FROM `%s` WHERE char_id='%d'",char_db,char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if(sql_res == NULL) - return 0; //Eh? No guild? - - sql_row = mysql_fetch_row(sql_res); - guild_id = sql_row?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + guild_id = atoi(data); + } + else + { + guild_id = 0; + } + Sql_FreeResult(sql_handle); } if (guild_id == 0) return 0; //No guild... @@ -860,23 +827,28 @@ void inter_guild_sql_final(void) int search_guildname(char *str) { int guild_id; - char t_name[NAME_LENGTH*2]; + char esc_name[NAME_LENGTH*2+1]; - jstrescapecpy(t_name, str); + Sql_EscapeStringLen(sql_handle, esc_name, str, strnlen(str, NAME_LENGTH)); //Lookup guilds with the same name - sprintf (tmp_sql , "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, t_name); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, esc_name) ) + { + Sql_ShowDebug(sql_handle); return -1; } - sql_res = mysql_store_result(&mysql_handle) ; - if(sql_res) - sql_row = mysql_fetch_row(sql_res); - - guild_id = (sql_row&&sql_res&&sql_row[0])?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + char* data; + + Sql_GetData(sql_handle, 0, &data, NULL); + guild_id = atoi(data); + } + else + { + guild_id = 0; + } + Sql_FreeResult(sql_handle); return guild_id; } @@ -1228,56 +1200,58 @@ int mapif_guild_castle_datasave(int castle_id,int index,int value) // <Agit return 0; } -int mapif_guild_castle_alldataload(int fd) { - struct guild_castle* gc = (struct guild_castle *)aMalloc(sizeof(struct guild_castle)); - int i, len = 4; - WFIFOHEAD(fd, len + MAX_GUILDCASTLE*sizeof(struct guild_castle)); - WFIFOW(fd,0) = 0x3842; - sprintf(tmp_sql,"SELECT * FROM `%s` ORDER BY `castle_id`", guild_castle_db); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - for(i = 0; ((sql_row = mysql_fetch_row(sql_res)) && i < MAX_GUILDCASTLE); i++) { - memset(gc, 0, sizeof(struct guild_castle)); - gc->castle_id = atoi(sql_row[0]); - gc->guild_id = atoi(sql_row[1]); - gc->economy = atoi(sql_row[2]); - gc->defense = atoi(sql_row[3]); - gc->triggerE = atoi(sql_row[4]); - gc->triggerD = atoi(sql_row[5]); - gc->nextTime = atoi(sql_row[6]); - gc->payTime = atoi(sql_row[7]); - gc->createTime = atoi(sql_row[8]); - gc->visibleC = atoi(sql_row[9]); - gc->guardian[0].visible = atoi(sql_row[10]); - gc->guardian[1].visible = atoi(sql_row[11]); - gc->guardian[2].visible = atoi(sql_row[12]); - gc->guardian[3].visible = atoi(sql_row[13]); - gc->guardian[4].visible = atoi(sql_row[14]); - gc->guardian[5].visible = atoi(sql_row[15]); - gc->guardian[6].visible = atoi(sql_row[16]); - gc->guardian[7].visible = atoi(sql_row[17]); - gc->guardian[0].visible = atoi(sql_row[18]); - gc->guardian[1].visible = atoi(sql_row[19]); - gc->guardian[2].visible = atoi(sql_row[20]); - gc->guardian[3].visible = atoi(sql_row[21]); - gc->guardian[4].visible = atoi(sql_row[22]); - gc->guardian[5].visible = atoi(sql_row[23]); - gc->guardian[6].visible = atoi(sql_row[24]); - gc->guardian[7].visible = atoi(sql_row[25]); - memcpy(WFIFOP(fd,len), gc, sizeof(struct guild_castle)); - len += sizeof(struct guild_castle); - } - mysql_free_result(sql_res); - } - WFIFOW(fd,2) = len; - WFIFOSET(fd,len); - - aFree(gc); +int mapif_guild_castle_alldataload(int fd) +{ + struct guild_castle s_gc; + struct guild_castle* gc = &s_gc; + int i; + int off; + char* data; + WFIFOHEAD(fd, 4 + MAX_GUILDCASTLE*sizeof(struct guild_castle)); + WFIFOW(fd, 0) = 0x3842; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, " + "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`," + "`Ghp0`, `Ghp1`, `Ghp2`, `Ghp3`, `Ghp4`, `Ghp5`, `Ghp6`, `Ghp7` FROM `%s` ORDER BY `castle_id`", guild_castle_db) ) + Sql_ShowDebug(sql_handle); + for( i = 0, off = 4; i < MAX_GUILDCASTLE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + memset(gc, 0, sizeof(struct guild_castle)); + + Sql_GetData(sql_handle, 0, &data, NULL); gc->castle_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); gc->guild_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); gc->economy = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); gc->defense = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); gc->triggerE = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); gc->triggerD = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); gc->nextTime = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); gc->payTime = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); gc->createTime = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); gc->visibleC = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); gc->guardian[0].visible = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); gc->guardian[1].visible = atoi(data); + Sql_GetData(sql_handle, 12, &data, NULL); gc->guardian[2].visible = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); gc->guardian[3].visible = atoi(data); + Sql_GetData(sql_handle, 14, &data, NULL); gc->guardian[4].visible = atoi(data); + Sql_GetData(sql_handle, 15, &data, NULL); gc->guardian[5].visible = atoi(data); + Sql_GetData(sql_handle, 16, &data, NULL); gc->guardian[6].visible = atoi(data); + Sql_GetData(sql_handle, 17, &data, NULL); gc->guardian[7].visible = atoi(data); + Sql_GetData(sql_handle, 18, &data, NULL); gc->guardian[0].hp = atoi(data); + Sql_GetData(sql_handle, 19, &data, NULL); gc->guardian[1].hp = atoi(data); + Sql_GetData(sql_handle, 20, &data, NULL); gc->guardian[2].hp = atoi(data); + Sql_GetData(sql_handle, 21, &data, NULL); gc->guardian[3].hp = atoi(data); + Sql_GetData(sql_handle, 22, &data, NULL); gc->guardian[4].hp = atoi(data); + Sql_GetData(sql_handle, 23, &data, NULL); gc->guardian[5].hp = atoi(data); + Sql_GetData(sql_handle, 24, &data, NULL); gc->guardian[6].hp = atoi(data); + Sql_GetData(sql_handle, 25, &data, NULL); gc->guardian[7].hp = atoi(data); + + memcpy(WFIFOP(fd, off), gc, sizeof(struct guild_castle)); + off += sizeof(struct guild_castle); + } + Sql_FreeResult(sql_handle); + WFIFOW(fd, 2) = off; + WFIFOSET(fd, off); + return 0; } @@ -1462,11 +1436,8 @@ int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int fl g->save_flag |= GS_EXPULSION; }else{ // Unknown guild, just update the player - sprintf(tmp_sql, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'",char_db, account_id,char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) + Sql_ShowDebug(sql_handle); /* mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes); */ } @@ -1542,66 +1513,39 @@ int mapif_parse_BreakGuild(int fd,int guild_id) // Delete guild from sql //printf("- Delete guild %d from guild\n",guild_id); - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) ) + Sql_ShowDebug(sql_handle); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) ) + Sql_ShowDebug(sql_handle); //printf("- Update guild %d of char\n",guild_id); - sprintf(tmp_sql, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'",char_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) ) + Sql_ShowDebug(sql_handle); mapif_guild_broken(guild_id,0); - + if(log_inter) inter_log("guild %s (id=%d) broken\n",g->name,guild_id); - + //Remove the guild from memory. [Skotlex] idb_remove(guild_db_, guild_id); return 0; diff --git a/src/char_sql/int_guild.h b/src/char_sql/int_guild.h index f8b3e98c5..ade191e9f 100644 --- a/src/char_sql/int_guild.h +++ b/src/char_sql/int_guild.h @@ -4,17 +4,6 @@ #ifndef _INT_GUILD_SQL_H_ #define _INT_GUILD_SQL_H_ -int inter_guild_parse_frommap(int fd); -int inter_guild_sql_init(void); -void inter_guild_sql_final(void); -int inter_guild_mapif_init(int fd); -int inter_guild_leave(int guild_id,int account_id,int char_id); -int mapif_parse_BreakGuild(int fd,int guild_id); -int inter_guild_broken(int guild_id); -int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender); -int inter_guild_CharOnline(int char_id, int guild_id); -int inter_guild_CharOffline(int char_id, int guild_id); - #define GS_BASIC 0x0001 #define GS_MEMBER 0x0002 #define GS_POSITION 0x0004 @@ -29,6 +18,20 @@ int inter_guild_CharOffline(int char_id, int guild_id); #define GS_BASIC_MASK (GS_BASIC | GS_EMBLEM | GS_CONNECT | GS_LEVEL | GS_MES) #define GS_REMOVE 0x8000 +struct guild; +struct guild_castle; + +int inter_guild_parse_frommap(int fd); +int inter_guild_sql_init(void); +void inter_guild_sql_final(void); +int inter_guild_mapif_init(int fd); +int inter_guild_leave(int guild_id,int account_id,int char_id); +int mapif_parse_BreakGuild(int fd,int guild_id); +int inter_guild_broken(int guild_id); +int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender); +int inter_guild_CharOnline(int char_id, int guild_id); +int inter_guild_CharOffline(int char_id, int guild_id); + //For the TXT->SQL converter. int inter_guild_tosql(struct guild *g,int flag); int inter_guildcastle_tosql(struct guild_castle *gc); diff --git a/src/char_sql/int_homun.c b/src/char_sql/int_homun.c index 42f4ef225..5c0c81f05 100644 --- a/src/char_sql/int_homun.c +++ b/src/char_sql/int_homun.c @@ -1,14 +1,19 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "char.h" +#include "../common/mmo.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/utils.h" +#include "../common/sql.h" +#include "char.h" +#include "inter.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> struct s_homunculus *homun_pt; @@ -68,154 +73,150 @@ int mapif_homunculus_created(int fd, int account_id, struct s_homunculus *sh, un // Save/Update Homunculus Skills int mapif_save_homunculus_skills(struct s_homunculus *hd) { + SqlStmt* stmt; int i; - for(i=0; i<MAX_HOMUNSKILL; i++) + stmt = SqlStmt_Malloc(sql_handle); + if( SQL_ERROR == SqlStmt_Prepare(stmt, "REPLACE INTO `skill_homunculus` (`homun_id`, `id`, `lv`) VALUES (%d, ?, ?)", hd->hom_id) ) + SqlStmt_ShowDebug(stmt); + for( i = 0; i < MAX_HOMUNSKILL; ++i ) { - if(hd->hskill[i].id != 0 && hd->hskill[i].lv != 0 ) + if( hd->hskill[i].id > 0 && hd->hskill[i].lv != 0 ) { - sprintf(tmp_sql,"REPLACE INTO `skill_homunculus` (`homun_id`, `id`, `lv`) VALUES (%d, %d, %d)", - hd->hom_id, hd->hskill[i].id, hd->hskill[i].lv); - - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + SqlStmt_BindParam(stmt, 0, SQLDT_USHORT, &hd->hskill[i].id, 0); + SqlStmt_BindParam(stmt, 1, SQLDT_USHORT, &hd->hskill[i].lv, 0); + if( SQL_ERROR == SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); return 0; } } } + SqlStmt_Free(stmt); return 1; } int mapif_save_homunculus(int fd, int account_id, struct s_homunculus *hd) { - int flag =1; - char t_name[NAME_LENGTH*2]; - jstrescapecpy(t_name, hd->name); + int flag = 1; + char esc_name[NAME_LENGTH*2+1]; - if(hd->hom_id==0) // new homunculus - { - sprintf(tmp_sql, "INSERT INTO `homunculus` " + Sql_EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH)); + + if( hd->hom_id == 0 ) + {// new homunculus + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `homunculus` " "(`char_id`, `class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) " "VALUES ('%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - hd->char_id, hd->class_,t_name,hd->level,hd->exp,hd->intimacy,hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, - hd->hp,hd->max_hp,hd->sp,hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize); - + hd->char_id, hd->class_, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize) ) + { + Sql_ShowDebug(sql_handle); + flag = 0; + } + else + { + hd->hom_id = (int)Sql_LastInsertId(sql_handle); + } } else { - sprintf(tmp_sql, "UPDATE `homunculus` SET `char_id`='%d', `class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", - hd->char_id, hd->class_,t_name,hd->level,hd->exp,hd->intimacy,hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, - hd->hp,hd->max_hp,hd->sp,hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id); - } - - if(mysql_query(&mysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - flag = 0; + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `homunculus` SET `char_id`='%d', `class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", + hd->char_id, hd->class_, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, + hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) ) + { + Sql_ShowDebug(sql_handle); + flag = 0; + } + else + { + flag = mapif_save_homunculus_skills(hd); + mapif_saved_homunculus(fd, account_id, flag); + } } - if(hd->hom_id==0 && flag!=0) - hd->hom_id = (int)mysql_insert_id(&mysql_handle); // new homunculus - else - { - flag = mapif_save_homunculus_skills(hd); - mapif_saved_homunculus(fd, account_id, flag); - } return flag; } // Load an homunculus -int mapif_load_homunculus(int fd){ +int mapif_load_homunculus(int fd) +{ int i; - RFIFOHEAD(fd); - memset(homun_pt, 0, sizeof(struct s_homunculus)); + char* data; + size_t len; - sprintf(tmp_sql,"SELECT `homun_id`,`char_id`,`class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `homunculus` WHERE `homun_id`='%u'", RFIFOL(fd,6)); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + memset(homun_pt, 0, sizeof(struct s_homunculus)); + RFIFOHEAD(fd); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `homunculus` WHERE `homun_id`='%u'", RFIFOL(fd,6)) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { - sql_row = mysql_fetch_row(sql_res); - - homun_pt->hom_id = RFIFOL(fd,6) ; //RFIFOL(fd,2); - homun_pt->class_ = atoi(sql_row[2]); - strncpy(homun_pt->name, sql_row[3], NAME_LENGTH); - homun_pt->char_id = atoi(sql_row[1]); - homun_pt->level = atoi(sql_row[4]); - homun_pt->exp = atoi(sql_row[5]); - homun_pt->intimacy = atoi(sql_row[6]); - homun_pt->hunger = atoi(sql_row[7]); - homun_pt->str = atoi(sql_row[8]); - homun_pt->agi = atoi(sql_row[9]); - homun_pt->vit = atoi(sql_row[10]); - homun_pt->int_ = atoi(sql_row[11]); - homun_pt->dex = atoi(sql_row[12]); - homun_pt->luk = atoi(sql_row[13]); - homun_pt->hp = atoi(sql_row[14]); - homun_pt->max_hp = atoi(sql_row[15]); - homun_pt->sp = atoi(sql_row[16]); - homun_pt->max_sp = atoi(sql_row[17]); - homun_pt->skillpts = atoi(sql_row[18]); - homun_pt->rename_flag = atoi(sql_row[19]); - homun_pt->vaporize = atoi(sql_row[20]); + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + homun_pt->hom_id = RFIFOL(fd,6); + Sql_GetData(sql_handle, 1, &data, NULL); homun_pt->char_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); homun_pt->class_ = atoi(data); + Sql_GetData(sql_handle, 3, &data, &len); memcpy(homun_pt->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 4, &data, NULL); homun_pt->level = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); homun_pt->exp = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); homun_pt->intimacy = (unsigned int)strtoul(data, NULL, 10); + homun_pt->intimacy = cap_value(homun_pt->intimacy, 0, 100000); + Sql_GetData(sql_handle, 7, &data, NULL); homun_pt->hunger = atoi(data); + homun_pt->hunger = cap_value(homun_pt->hunger, 0, 100); + Sql_GetData(sql_handle, 8, &data, NULL); homun_pt->str = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); homun_pt->agi = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); homun_pt->vit = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); homun_pt->int_ = atoi(data); + Sql_GetData(sql_handle, 12, &data, NULL); homun_pt->dex = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); homun_pt->luk = atoi(data); + Sql_GetData(sql_handle, 14, &data, NULL); homun_pt->hp = atoi(data); + Sql_GetData(sql_handle, 15, &data, NULL); homun_pt->max_hp = atoi(data); + Sql_GetData(sql_handle, 16, &data, NULL); homun_pt->sp = atoi(data); + Sql_GetData(sql_handle, 17, &data, NULL); homun_pt->max_sp = atoi(data); + Sql_GetData(sql_handle, 18, &data, NULL); homun_pt->skillpts = atoi(data); + Sql_GetData(sql_handle, 19, &data, NULL); homun_pt->rename_flag = atoi(data); + Sql_GetData(sql_handle, 20, &data, NULL); homun_pt->vaporize = atoi(data); + + Sql_FreeResult(sql_handle); } - if(homun_pt->hunger < 0) - homun_pt->hunger = 0; - else if(homun_pt->hunger > 100) - homun_pt->hunger = 100; - if(homun_pt->intimacy > 100000) - homun_pt->intimacy = 100000; - - mysql_free_result(sql_res); // Load Homunculus Skill - memset(homun_pt->hskill, 0, sizeof(homun_pt->hskill)); - - sprintf(tmp_sql,"SELECT `id`,`lv` FROM `skill_homunculus` WHERE `homun_id`=%d",homun_pt->hom_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `skill_homunculus` WHERE `homun_id`=%d", homun_pt->hom_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle); - if(sql_res){ - while((sql_row = mysql_fetch_row(sql_res))){ - i = (atoi(sql_row[0])-HM_SKILLBASE-1); - homun_pt->hskill[i].id = atoi(sql_row[0]); - homun_pt->hskill[i].lv = atoi(sql_row[1]); - } - } - - mysql_free_result(sql_res); - - if (save_log) + while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { + // id + Sql_GetData(sql_handle, 0, &data, NULL); + i = atoi(data); + if( i < HM_SKILLBASE || i >= HM_SKILLBASE + MAX_HOMUNSKILL ) + continue;// invalid guild skill + homun_pt->hskill[i].id = (unsigned short)i; + // lv + Sql_GetData(sql_handle, 1, &data, NULL); + homun_pt->hskill[i].lv = (unsigned short)atoi(data); + } + Sql_FreeResult(sql_handle); + + if( save_log ) ShowInfo("Homunculus loaded (%d - %s).\n", homun_pt->hom_id, homun_pt->name); return mapif_info_homunculus(fd, RFIFOL(fd,2), homun_pt); } int inter_delete_homunculus(int hom_id) { - sprintf(tmp_sql, "DELETE FROM `homunculus` WHERE `homun_id` = '%u'", hom_id); - if(mysql_query(&mysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - - sprintf(tmp_sql, "DELETE FROM `skill_homunculus` WHERE `homun_id` = '%u'", hom_id); - if(mysql_query(&mysql_handle, tmp_sql)) + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `homunculus` WHERE `homun_id` = '%u'", hom_id) || + SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `skill_homunculus` WHERE `homun_id` = '%u'", hom_id) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(sql_handle); return 0; } return 1; diff --git a/src/char_sql/int_homun.h b/src/char_sql/int_homun.h index fa49c659f..d990b2219 100644 --- a/src/char_sql/int_homun.h +++ b/src/char_sql/int_homun.h @@ -4,6 +4,8 @@ #ifndef _INT_HOMUN_SQL_H_ #define _INT_HOMUN_SQL_H_ +struct s_homunculus; + int inter_homunculus_sql_init(void); void inter_homunculus_sql_final(void); int mapif_save_homunculus(struct s_homunculus *hd); diff --git a/src/char_sql/int_party.c b/src/char_sql/int_party.c index c1c09e9a4..f6d783b3b 100644 --- a/src/char_sql/int_party.c +++ b/src/char_sql/int_party.c @@ -1,18 +1,22 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - #include "../common/cbasetypes.h" +#include "../common/mmo.h" #include "../common/db.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/socket.h" #include "../common/showmsg.h" - +#include "../common/mapindex.h" +#include "../common/sql.h" #include "char.h" +#include "inter.h" +#include "int_party.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifndef TXT_SQL_CONVERT struct party_data { @@ -103,108 +107,88 @@ static void int_party_calc_state(struct party_data *p) int inter_party_tosql(struct party *p, int flag, int index) { // 'party' ('party_id','name','exp','item','leader_id','leader_char') - char t_name[NAME_LENGTH*2]; //Required for jstrescapecpy [Skotlex] + char esc_name[NAME_LENGTH*2+1];// escaped party name int party_id; - if (p == NULL || p->party_id == 0) + + if( p == NULL || p->party_id == 0 ) return 0; party_id = p->party_id; #ifdef NOISY ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name); #endif - jstrescapecpy(t_name, p->name); + Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); #ifndef TXT_SQL_CONVERT - if (flag&PS_BREAK) { //Break the party + if( flag & PS_BREAK ) + {// Break the party // we'll skip name-checking and just reset everyone with the same party id [celest] - sprintf (tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + Sql_ShowDebug(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + Sql_ShowDebug(sql_handle); //Remove from memory idb_remove(party_db_, party_id); return 1; } #endif //TXT_SQL_CONVERT - if(flag&PS_CREATE) { //Create party + if( flag & PS_CREATE ) + {// Create party #ifndef TXT_SQL_CONVERT - sprintf(tmp_sql, "INSERT INTO `%s` " + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%s', '%d', '%d', '%d', '%d')", - party_db, t_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - if(mysql_field_count(&mysql_handle) == 0 && - mysql_insert_id(&mysql_handle) != 0) - party_id = p->party_id = (int)mysql_insert_id(&mysql_handle); - else //Failed to retrieve ID?? - return 0; + party_id = p->party_id = (int)Sql_LastInsertId(sql_handle); #else //During conversion, you want to specify the id, and allow overwriting //(in case someone is re-running the process. - sprintf(tmp_sql, "REPLACE INTO `%s` " + + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` " "(`party_id`, `name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d')", - party_db, p->party_id, t_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + party_db, p->party_id, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } #endif } #ifndef TXT_SQL_CONVERT - if (flag&PS_BASIC) { - //Update party info. - sprintf(tmp_sql, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", - party_db, t_name, p->exp, p->item, party_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( flag & PS_BASIC ) + {// Update party info. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", + party_db, esc_name, p->exp, p->item, party_id) ) + Sql_ShowDebug(sql_handle); } - if (flag&PS_LEADER) { - //Update leader - sprintf(tmp_sql, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", - party_db, p->member[index].account_id, p->member[index].char_id, party_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( flag & PS_LEADER ) + {// Update leader + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", + party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) + Sql_ShowDebug(sql_handle); } - if (flag&PS_ADDMEMBER) { - //Add one party member. - sprintf (tmp_sql, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", - char_db, party_id, p->member[index].account_id, p->member[index].char_id); - if (mysql_query (&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( flag & PS_ADDMEMBER ) + {// Add one party member. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", + char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + Sql_ShowDebug(sql_handle); } - if (flag&PS_DELMEMBER) { - //Remove one party member. - sprintf (tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", - char_db, party_id, p->member[index].account_id, p->member[index].char_id); - if (mysql_query (&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( flag & PS_DELMEMBER ) + {// Remove one party member. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", + char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) + Sql_ShowDebug(sql_handle); } #endif //TXT_SQL_CONVERT - if (save_log) + if( save_log ) ShowInfo("Party Saved (%d - %s)\n", party_id, p->name); return 1; } @@ -212,74 +196,69 @@ int inter_party_tosql(struct party *p, int flag, int index) // Read party from mysql struct party_data *inter_party_fromsql(int party_id) { - int leader_id = 0, leader_char = 0; - struct party_data *p; + int leader_id = 0; + int leader_char = 0; + struct party_data* p; + struct party_member* m; + char* data; + size_t len; + int i; + #ifdef NOISY ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id); #endif - if (party_id <=0) + if( party_id <= 0 ) return NULL; //Load from memory - if ((p = idb_get(party_db_, party_id)) != NULL) + p = idb_get(party_db_, party_id); + if( p != NULL ) return p; - + p = party_pt; memset(p, 0, sizeof(struct party_data)); - sprintf(tmp_sql, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", - party_db, party_id); // TBR - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + { + Sql_ShowDebug(sql_handle); return NULL; } - sql_res = mysql_store_result(&mysql_handle) ; - if (!sql_res) + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) return NULL; - sql_row = mysql_fetch_row(sql_res); - if (!sql_row) { - mysql_free_result(sql_res); - return NULL; - } + p->party.party_id = party_id; - strncpy(p->party.name, sql_row[1], NAME_LENGTH); - p->party.exp = atoi(sql_row[2])?1:0; - p->party.item = atoi(sql_row[3]); - leader_id = atoi(sql_row[4]); - leader_char = atoi(sql_row[5]); - mysql_free_result(sql_res); + Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); + Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data); + Sql_FreeResult(sql_handle); // Load members - sprintf(tmp_sql,"SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", - char_db, party_id); // TBR - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) + { + Sql_ShowDebug(sql_handle); return NULL; } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - int i; - for (i = 0; i<MAX_PARTY && (sql_row = mysql_fetch_row(sql_res)); i++) { - struct party_member *m = &p->party.member[i]; - m->account_id = atoi(sql_row[0]); - m->char_id = atoi(sql_row[1]); - m->leader = (m->account_id == leader_id && m->char_id == leader_char)?1:0; - memcpy(m->name, sql_row[2], NAME_LENGTH); - m->lv = atoi(sql_row[3]); - m->map = mapindex_name2id(sql_row[4]); - m->online = atoi(sql_row[5])?1:0; - m->class_ = atoi(sql_row[6]); - } - mysql_free_result(sql_res); - } - - if (save_log) - ShowInfo("Party loaded (%d - %s).\n",party_id, p->party.name); + for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + m = &p->party.member[i]; + Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); + Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data); + Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0); + Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); + m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0); + } + Sql_FreeResult(sql_handle); + + if( save_log ) + ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); //Add party to memory. - p = aCalloc(1, sizeof(struct party_data)); + CREATE(p, struct party_data, 1); memcpy(p, party_pt, sizeof(struct party_data)); //init state int_party_calc_state(p); @@ -299,13 +278,9 @@ int inter_party_sql_init(void) /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex] ShowStatus("cleaning party table...\n"); - sprintf (tmp_sql, - "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL", - party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL", + party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) ) + Sql_ShowDebug(sql_handle); */ return 0; } @@ -318,27 +293,23 @@ void inter_party_sql_final(void) } // Search for the party according to its name -struct party_data* search_partyname(char *str) +struct party_data* search_partyname(char* str) { - char t_name[NAME_LENGTH*2]; - int party_id; - - sprintf(tmp_sql,"SELECT `party_id` FROM `%s` WHERE `name`='%s'",party_db, jstrescapecpy(t_name,str)); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res==NULL || mysql_num_rows(sql_res)<=0) + char esc_name[NAME_LENGTH*2+1]; + char* data; + struct party_data* p = NULL; + + Sql_EscapeStringLen(sql_handle, esc_name, str, strnlen(str, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) ) + Sql_ShowDebug(sql_handle); + else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { - if (sql_res) mysql_free_result(sql_res); - return NULL; + Sql_GetData(sql_handle, 0, &data, NULL); + p = inter_party_fromsql(atoi(data)); } - sql_row = mysql_fetch_row(sql_res); - party_id = sql_row?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + Sql_FreeResult(sql_handle); - return inter_party_fromsql(party_id); + return p; } // Returns whether this party can keep having exp share or not. @@ -627,12 +598,10 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) int i,j=-1; p = inter_party_fromsql(party_id); - if (!p) { //Party does not exists? - sprintf(tmp_sql, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( p == NULL ) + {// Party does not exists? + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + Sql_ShowDebug(sql_handle); return 0; } @@ -809,26 +778,27 @@ int inter_party_leave(int party_id,int account_id, int char_id) return mapif_parse_PartyLeave(-1,party_id,account_id, char_id); } -int inter_party_CharOnline(int char_id, int party_id) { - struct party_data *p; - int i; - - if (party_id == -1) { - //Get party_id from the database - sprintf (tmp_sql , "SELECT party_id FROM `%s` WHERE char_id='%d'",char_db,char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); +int inter_party_CharOnline(int char_id, int party_id) +{ + struct party_data* p; + int i; + + if( party_id == -1 ) + {// Get party_id from the database + char* data; + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if(sql_res == NULL) + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) return 0; //Eh? No party? - - sql_row = mysql_fetch_row(sql_res); - party_id = sql_row?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + + Sql_GetData(sql_handle, 0, &data, NULL); + party_id = atoi(data); + Sql_FreeResult(sql_handle); } if (party_id == 0) return 0; //No party... @@ -859,22 +829,22 @@ int inter_party_CharOffline(int char_id, int party_id) { struct party_data *p=NULL; int i; - if (party_id == -1) { - //Get guild_id from the database - sprintf (tmp_sql , "SELECT party_id FROM `%s` WHERE char_id='%d'",char_db,char_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( party_id == -1 ) + {// Get guild_id from the database + char* data; + + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if(sql_res == NULL) + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) return 0; //Eh? No party? - - sql_row = mysql_fetch_row(sql_res); - party_id = sql_row?atoi(sql_row[0]):0; - mysql_free_result(sql_res); + + Sql_GetData(sql_handle, 0, &data, NULL); + party_id = atoi(data); + Sql_FreeResult(sql_handle); } if (party_id == 0) return 0; //No party... diff --git a/src/char_sql/int_party.h b/src/char_sql/int_party.h index c244ab59e..d7965c33b 100644 --- a/src/char_sql/int_party.h +++ b/src/char_sql/int_party.h @@ -18,6 +18,8 @@ //Specify that this party must be deleted. #define PS_BREAK 0x20 +struct party; + int inter_party_parse_frommap(int fd); int inter_party_sql_init(void); void inter_party_sql_final(void); diff --git a/src/char_sql/int_pet.c b/src/char_sql/int_pet.c index 6352412ce..3ce7c4559 100644 --- a/src/char_sql/int_pet.c +++ b/src/char_sql/int_pet.c @@ -1,53 +1,52 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "char.h" +#include "../common/mmo.h" #include "../common/malloc.h" +#include "../common/socket.h" #include "../common/strlib.h" #include "../common/showmsg.h" +#include "../common/utils.h" +#include "../common/sql.h" +#include "char.h" +#include "inter.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> struct s_pet *pet_pt; //--------------------------------------------------------- -int inter_pet_tosql(int pet_id, struct s_pet *p) { +int inter_pet_tosql(int pet_id, struct s_pet* p) +{ //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - char t_name[NAME_LENGTH*2]; - - jstrescapecpy(t_name, p->name); - - if(p->hungry < 0) - p->hungry = 0; - else if(p->hungry > 100) - p->hungry = 100; - if(p->intimate < 0) - p->intimate = 0; - else if(p->intimate > 1000) - p->intimate = 1000; - if (pet_id == -1) //New pet. - sprintf(tmp_sql,"INSERT INTO `%s` " + char esc_name[NAME_LENGTH*2+1];// escaped pet name + + Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + p->hungry = cap_value(p->hungry, 0, 100); + p->intimate = cap_value(p->intimate, 0, 1000); + + if( pet_id == -1 ) + {// New pet. + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", - pet_db, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate); - - else //Update pet. - sprintf(tmp_sql, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", - pet_db, p->class_, t_name, p->account_id, p->char_id, p->level, p->egg_id, - p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } else if (pet_id == -1) { //New pet inserted. - if(mysql_field_count(&mysql_handle) == 0 && - mysql_insert_id(&mysql_handle) != 0) { - p->pet_id = pet_id = (int)mysql_insert_id(&mysql_handle); - } else { - ShowError("inter_pet_tosql: Failed to retrieve new pet_id for '%s'. Pet creation aborted.\n", p->name); + pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, + p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate) ) + { + Sql_ShowDebug(sql_handle); + return 0; + } + p->pet_id = (int)Sql_LastInsertId(sql_handle); + } + else + {// Update pet. + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", + pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, + p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } } @@ -57,7 +56,10 @@ int inter_pet_tosql(int pet_id, struct s_pet *p) { return 1; } #ifndef TXT_SQL_CONVERT -int inter_pet_fromsql(int pet_id, struct s_pet *p){ +int inter_pet_fromsql(int pet_id, struct s_pet* p) +{ + char* data; + size_t len; #ifdef NOISY ShowInfo("Loading pet (%d)...\n",pet_id); @@ -66,42 +68,35 @@ int inter_pet_fromsql(int pet_id, struct s_pet *p){ //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - sprintf(tmp_sql,"SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + { + Sql_ShowDebug(sql_handle); return 0; } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { - sql_row = mysql_fetch_row(sql_res); + if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + { p->pet_id = pet_id; - p->class_ = atoi(sql_row[1]); - strncpy(p->name, sql_row[2], NAME_LENGTH); - p->account_id = atoi(sql_row[3]); - p->char_id = atoi(sql_row[4]); - p->level = atoi(sql_row[5]); - p->egg_id = atoi(sql_row[6]); - p->equip = atoi(sql_row[7]); - p->intimate = atoi(sql_row[8]); - p->hungry = atoi(sql_row[9]); - p->rename_flag = atoi(sql_row[10]); - p->incuvate = atoi(sql_row[11]); + Sql_GetData(sql_handle, 1, &data, NULL); p->class_ = atoi(data); + Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + Sql_GetData(sql_handle, 3, &data, NULL); p->account_id = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); p->char_id = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); p->level = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); p->egg_id = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); p->equip = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); p->intimate = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); p->hungry = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); p->incuvate = atoi(data); + + Sql_FreeResult(sql_handle); + + p->hungry = cap_value(p->hungry, 0, 100); + p->intimate = cap_value(p->intimate, 0, 1000); + + if( save_log ) + ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); } - if(p->hungry < 0) - p->hungry = 0; - else if(p->hungry > 100) - p->hungry = 100; - if(p->intimate < 0) - p->intimate = 0; - else if(p->intimate > 1000) - p->intimate = 1000; - - mysql_free_result(sql_res); - - if (save_log) - ShowInfo("Pet loaded (%d - %s).\n", pet_id, p->name); return 0; } //---------------------------------------------- @@ -119,11 +114,8 @@ void inter_pet_sql_final(void){ int inter_pet_delete(int pet_id){ ShowInfo("delete pet request: %d...\n",pet_id); - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `pet_id`='%d'",pet_db, pet_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + Sql_ShowDebug(sql_handle); return 0; } //------------------------------------------------------ diff --git a/src/char_sql/int_pet.h b/src/char_sql/int_pet.h index 5c1955857..733468c77 100644 --- a/src/char_sql/int_pet.h +++ b/src/char_sql/int_pet.h @@ -4,6 +4,8 @@ #ifndef _INT_PET_SQL_H_ #define _INT_PET_SQL_H_ +struct s_pet; + int inter_pet_init(void); void inter_pet_sql_final(void); int inter_pet_save(void); diff --git a/src/char_sql/int_storage.c b/src/char_sql/int_storage.c index a52e5b530..b13f37200 100644 --- a/src/char_sql/int_storage.c +++ b/src/char_sql/int_storage.c @@ -1,17 +1,19 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -// original code from athena -// SQL conversion by Jioh L. Jung +#include "../common/mmo.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/strlib.h" // StringBuf +#include "../common/sql.h" +#include "char.h" +#include "inter.h" #include <stdio.h> #include <string.h> #include <stdlib.h> -#include "char.h" -#include "itemdb.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" #define STORAGE_MEMINC 16 @@ -19,166 +21,130 @@ // reset by inter_config_read() struct storage *storage_pt=NULL; struct guild_storage *guild_storage_pt=NULL; - #endif //TXT_SQL_CONVERT -// storage data -> DB conversion -int storage_tosql(int account_id,struct storage *p){ - int i,j; -// int eqcount=1; -// int noteqcount=1; - int count=0; - struct itemtmp mapitem[MAX_STORAGE]; - for(i=0;i<MAX_STORAGE;i++){ - if(p->storage_[i].nameid>0){ - mapitem[count].flag=0; - mapitem[count].id = p->storage_[i].id; - mapitem[count].nameid=p->storage_[i].nameid; - mapitem[count].amount = p->storage_[i].amount; - mapitem[count].equip = p->storage_[i].equip; - mapitem[count].identify = p->storage_[i].identify; - mapitem[count].refine = p->storage_[i].refine; - mapitem[count].attribute = p->storage_[i].attribute; - for(j=0; j<MAX_SLOTS; j++) - mapitem[count].card[j] = p->storage_[i].card[j]; - count++; - } - } - memitemdata_to_sql(mapitem, count, account_id,TABLE_STORAGE); - - //printf ("storage dump to DB - id: %d (total: %d)\n", account_id, j); +/// Save guild_storage data to sql +int storage_tosql(int account_id,struct storage* p) +{ + memitemdata_to_sql(p->storage_, MAX_STORAGE, account_id, TABLE_STORAGE); + //ShowInfo ("storage save to DB - account: %d\n", account_id); return 0; } -#ifndef TXT_SQL_CONVERT -// DB -> storage data conversion -int storage_fromsql(int account_id, struct storage *p){ - int i=0,j; - char * str_p = tmp_sql; +#ifndef TXT_SQL_CONVERT +/// Load guild_storage data to mem +int storage_fromsql(int account_id, struct storage* p) +{ + StringBuf buf; + struct item* item; + char* data; + int i; + int j; - memset(p,0,sizeof(struct storage)); //clean up memory + memset(p, 0, sizeof(struct storage)); //clean up memory p->storage_amount = 0; p->account_id = account_id; // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} - str_p += sprintf(str_p,"SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`"); - - for (j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p, ", `card%d`", j); - - str_p += sprintf(str_p," FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); - - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle) ; - - if (sql_res) { - while((sql_row = mysql_fetch_row(sql_res)) && i<MAX_STORAGE) { //start to fetch - p->storage_[i].id= atoi(sql_row[0]); - p->storage_[i].nameid= atoi(sql_row[1]); - p->storage_[i].amount= atoi(sql_row[2]); - p->storage_[i].equip= atoi(sql_row[3]); - p->storage_[i].identify= atoi(sql_row[4]); - p->storage_[i].refine= atoi(sql_row[5]); - p->storage_[i].attribute= atoi(sql_row[6]); - for (j=0; j<MAX_SLOTS; j++) - p->storage_[i].card[j]= atoi(sql_row[7+j]); - i++; + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ",`card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); + + if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + + StringBuf_Destroy(&buf); + + for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + item = &p->storage_[i]; + Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); + for( j = 0; j < MAX_SLOTS; ++j ) + { + Sql_GetData(sql_handle, 7+j, &data, NULL); item->card[j] = atoi(data); } - p->storage_amount = i; - mysql_free_result(sql_res); } + p->storage_amount = i; + Sql_FreeResult(sql_handle); - ShowInfo ("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount); + ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount); return 1; } #endif //TXT_SQL_CONVERT -// Save guild_storage data to sql -int guild_storage_tosql(int guild_id, struct guild_storage *p){ - int i,j; -// int eqcount=1; -// int noteqcount=1; - int count=0; - struct itemtmp mapitem[MAX_GUILD_STORAGE]; - for(i=0;i<MAX_GUILD_STORAGE;i++){ - if(p->storage_[i].nameid>0){ - mapitem[count].flag=0; - mapitem[count].id = p->storage_[i].id; - mapitem[count].nameid=p->storage_[i].nameid; - mapitem[count].amount = p->storage_[i].amount; - mapitem[count].equip = p->storage_[i].equip; - mapitem[count].identify = p->storage_[i].identify; - mapitem[count].refine = p->storage_[i].refine; - mapitem[count].attribute = p->storage_[i].attribute; - for (j=0; j<MAX_SLOTS; j++) - mapitem[count].card[j] = p->storage_[i].card[j]; - count++; - } - } - memitemdata_to_sql(mapitem, count, guild_id,TABLE_GUILD_STORAGE); - - ShowInfo ("guild storage save to DB - id: %d (total: %d)\n", guild_id,i); +/// Save guild_storage data to sql +int guild_storage_tosql(int guild_id, struct guild_storage* p) +{ + memitemdata_to_sql(p->storage_, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE); + ShowInfo ("guild storage save to DB - guild: %d\n", guild_id); return 0; } + #ifndef TXT_SQL_CONVERT -// Load guild_storage data to mem -int guild_storage_fromsql(int guild_id, struct guild_storage *p){ - int i=0,j; - struct guild_storage *gs=guild_storage_pt; - char * str_p = tmp_sql; - p=gs; - - memset(p,0,sizeof(struct guild_storage)); //clean up memory +/// Load guild_storage data to mem +int guild_storage_fromsql(int guild_id, struct guild_storage* p) +{ + StringBuf buf; + struct item* item; + char* data; + int i; + int j; + + memset(p, 0, sizeof(struct guild_storage)); //clean up memory p->storage_amount = 0; p->guild_id = guild_id; // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} - str_p += sprintf(str_p,"SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`"); - - for (j=0; j<MAX_SLOTS; j++) - str_p += sprintf(str_p, ", `card%d`", j); - - str_p += sprintf(str_p," FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); - - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle) ; - - if (sql_res) { - while((sql_row = mysql_fetch_row(sql_res)) && i < MAX_GUILD_STORAGE) { //start to fetch - p->storage_[i].id= atoi(sql_row[0]); - p->storage_[i].nameid= atoi(sql_row[1]); - p->storage_[i].amount= atoi(sql_row[2]); - p->storage_[i].equip= atoi(sql_row[3]); - p->storage_[i].identify= atoi(sql_row[4]); - p->storage_[i].refine= atoi(sql_row[5]); - p->storage_[i].attribute= atoi(sql_row[6]); - for (j=0; j<MAX_SLOTS; j++) - p->storage_[i].card[j] = atoi(sql_row[7+j]); - i++; + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`"); + for( j = 0; j < MAX_SLOTS; ++j ) + StringBuf_Printf(&buf, ",`card%d`", j); + StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); + + if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + Sql_ShowDebug(sql_handle); + + StringBuf_Destroy(&buf); + + for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + item = &p->storage_[i]; + Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); + Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); + Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); + Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); + Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); + for( j = 0; j < MAX_SLOTS; ++j ) + { + Sql_GetData(sql_handle, 7+j, &data, NULL); item->card[j] = atoi(data); } - p->storage_amount = i; - mysql_free_result(sql_res); } - ShowInfo ("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount); + p->storage_amount = i; + Sql_FreeResult(sql_handle); + + ShowInfo("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount); return 0; } //--------------------------------------------------------- // storage data initialize -int inter_storage_sql_init(void){ +int inter_storage_sql_init(void) +{ //memory alloc ShowDebug("interserver storage memory initialize....(%d byte)\n",sizeof(struct storage)); storage_pt = (struct storage*)aCalloc(sizeof(struct storage), 1); guild_storage_pt = (struct guild_storage*)aCalloc(sizeof(struct guild_storage), 1); -// memset(storage_pt,0,sizeof(struct storage)); //Calloc sets stuff to 0 already. [Skotlex] -// memset(guild_storage_pt,0,sizeof(struct guild_storage)); return 1; } @@ -192,20 +158,14 @@ void inter_storage_sql_final(void) // q?f[^? int inter_storage_delete(int account_id) { - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `account_id`='%d'",storage_db, account_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) ) + Sql_ShowDebug(sql_handle); return 0; } int inter_guild_storage_delete(int guild_id) { - sprintf(tmp_sql, "DELETE FROM `%s` WHERE `guild_id`='%d'",guild_storage_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) ) + Sql_ShowDebug(sql_handle); return 0; } @@ -213,7 +173,8 @@ int inter_guild_storage_delete(int guild_id) // packet from map server // recive packet about storage data -int mapif_load_storage(int fd,int account_id){ +int mapif_load_storage(int fd,int account_id) +{ //load from DB WFIFOHEAD(fd, sizeof(struct storage)+8); storage_fromsql(account_id, storage_pt); @@ -225,7 +186,8 @@ int mapif_load_storage(int fd,int account_id){ return 0; } // send ack to map server which is "storage data save ok." -int mapif_save_storage_ack(int fd,int account_id){ +int mapif_save_storage_ack(int fd,int account_id) +{ WFIFOHEAD(fd, 7); WFIFOW(fd,0)=0x3811; WFIFOL(fd,2)=account_id; @@ -236,40 +198,29 @@ int mapif_save_storage_ack(int fd,int account_id){ int mapif_load_guild_storage(int fd,int account_id,int guild_id) { - int guild_exist=1; - WFIFOHEAD(fd, sizeof(struct guild_storage)+12); - WFIFOW(fd,0)=0x3818; - -#if 0 // innodb guilds should render this check unnecessary [Aru] - // Check if guild exists, I may write a function for this later, coz I use it several times. - //printf("- Check if guild %d exists\n",g->guild_id); - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { - sql_row = mysql_fetch_row(sql_res); - guild_exist = atoi (sql_row[0]); - //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes")); - } - mysql_free_result(sql_res) ; //resource free -#endif - if(guild_exist==1) { - guild_storage_fromsql(guild_id,guild_storage_pt); - WFIFOW(fd,2)=sizeof(struct guild_storage)+12; - WFIFOL(fd,4)=account_id; - WFIFOL(fd,8)=guild_id; - memcpy(WFIFOP(fd,12),guild_storage_pt,sizeof(struct guild_storage)); - } - else { - WFIFOW(fd,2)=12; - WFIFOL(fd,4)=account_id; - WFIFOL(fd,8)=0; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + Sql_ShowDebug(sql_handle); + else if( Sql_NumRows(sql_handle) > 0 ) + {// guild exists + guild_storage_fromsql(guild_id, guild_storage_pt); + + WFIFOHEAD(fd, sizeof(struct guild_storage)+12); + WFIFOW(fd,0) = 0x3818; + WFIFOW(fd,2) = sizeof(struct guild_storage)+12; + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = guild_id; + memcpy(WFIFOP(fd,12), guild_storage_pt, sizeof(struct guild_storage)); + WFIFOSET(fd, WFIFOW(fd,2)); + return 0; } - WFIFOSET(fd,WFIFOW(fd,2)); - + // guild does not exist + Sql_FreeResult(sql_handle); + WFIFOHEAD(fd, 12); + WFIFOW(fd,0) = 0x3818; + WFIFOW(fd,2) = 12; + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = 0; + WFIFOSET(fd, 12); return 0; } int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail) @@ -287,13 +238,15 @@ int mapif_save_guild_storage_ack(int fd,int account_id,int guild_id,int fail) // packet from map server // recive request about storage data -int mapif_parse_LoadStorage(int fd){ +int mapif_parse_LoadStorage(int fd) +{ RFIFOHEAD(fd); mapif_load_storage(fd,RFIFOL(fd,2)); return 0; } // storage data recive and save -int mapif_parse_SaveStorage(int fd){ +int mapif_parse_SaveStorage(int fd) +{ int account_id; int len; RFIFOHEAD(fd); @@ -318,45 +271,38 @@ int mapif_parse_LoadGuildStorage(int fd) int mapif_parse_SaveGuildStorage(int fd) { - int guild_exist=1; int guild_id; int len; + RFIFOHEAD(fd); - guild_id=RFIFOL(fd,8); - len=RFIFOW(fd,2); - if(sizeof(struct guild_storage)!=len-12){ - ShowError("inter storage: data size error %d %d\n",sizeof(struct guild_storage),len-12); + guild_id = RFIFOL(fd,8); + len = RFIFOW(fd,2); + + if( sizeof(struct guild_storage) != len - 12 ) + { + ShowError("inter storage: data size error %d != %d\n", sizeof(struct guild_storage), len - 12); } - else { -#if 0 // Again, innodb key checks make the check pointless - // Check if guild exists, I may write a function for this later, coz I use it several times. - //printf("- Check if guild %d exists\n",g->guild_id); - sprintf(tmp_sql, "SELECT count(*) FROM `%s` WHERE `guild_id`='%d'",guild_db, guild_id); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res!=NULL && mysql_num_rows(sql_res)>0) { - sql_row = mysql_fetch_row(sql_res); - guild_exist = atoi (sql_row[0]); - //printf("- Check if guild %d exists : %s\n",g->guild_id,((guild_exist==0)?"No":"Yes")); + else + { + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + Sql_ShowDebug(sql_handle); + else if( Sql_NumRows(sql_handle) > 0 ) + {// guild exists + Sql_FreeResult(sql_handle); + memcpy(guild_storage_pt, RFIFOP(fd,12), sizeof(struct guild_storage)); + guild_storage_tosql(guild_id, guild_storage_pt); + mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0); + return 0; } - mysql_free_result(sql_res) ; //resource free -#endif - if(guild_exist==1) { - memcpy(guild_storage_pt,RFIFOP(fd,12),sizeof(struct guild_storage)); - guild_storage_tosql(guild_id,guild_storage_pt); - mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,0); - } - else - mapif_save_guild_storage_ack(fd,RFIFOL(fd,4),guild_id,1); + Sql_FreeResult(sql_handle); } + mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1); return 0; } -int inter_storage_parse_frommap(int fd){ +int inter_storage_parse_frommap(int fd) +{ RFIFOHEAD(fd); switch(RFIFOW(fd,0)){ case 0x3010: mapif_parse_LoadStorage(fd); break; diff --git a/src/char_sql/int_storage.h b/src/char_sql/int_storage.h index dd71ef9ed..7075e36ad 100644 --- a/src/char_sql/int_storage.h +++ b/src/char_sql/int_storage.h @@ -4,6 +4,9 @@ #ifndef _INT_STORAGE_SQL_H_ #define _INT_STORAGE_SQL_H_ +struct storage; +struct guild_storage; + int inter_storage_sql_init(void); void inter_storage_sql_final(void); int inter_storage_delete(int account_id); diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c index fbff7b7fb..201605bd6 100644 --- a/src/char_sql/inter.c +++ b/src/char_sql/inter.c @@ -1,34 +1,31 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include <stdio.h> -#include <string.h> -#include <stdlib.h> - -#include "char.h" +#include "../common/mmo.h" +#include "../common/db.h" #include "../common/malloc.h" #include "../common/strlib.h" #include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "char.h" #include "inter.h" #include "int_party.h" #include "int_guild.h" #include "int_storage.h" #include "int_pet.h" -#include "int_homun.h" //albator +#include "int_homun.h" + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> #define WISDATA_TTL (60*1000) // Wisƒf[ƒ^‚̶‘¶ŽžŠÔ(60•b) #define WISDELLIST_MAX 256 // Wisƒf[ƒ^휃ŠƒXƒg‚Ì—v‘f” -MYSQL mysql_handle; -MYSQL_RES* sql_res ; -MYSQL_ROW sql_row ; -int sql_fields, sql_cnt; -char tmp_sql[65535]; - -MYSQL lmysql_handle; -MYSQL_RES* lsql_res ; -MYSQL_ROW lsql_row ; +Sql* sql_handle = NULL; +Sql* lsql_handle = NULL; int char_server_port = 3306; char char_server_ip[32] = "127.0.0.1"; @@ -89,50 +86,59 @@ int inter_sql_test (void); #endif //TXT_SQL_CONVERT //-------------------------------------------------------- // Save registry to sql -int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type){ +int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type) +{ + struct global_reg* r; + SqlStmt* stmt; + int i; - int j; - char temp_str[64]; //Needs be twice the source to ensure it fits [Skotlex] - char temp_str2[512]; - if (account_id<=0) return 0; - reg->account_id=account_id; + if( account_id <= 0 ) + return 0; + reg->account_id = account_id; reg->char_id = char_id; - switch (type) { - case 3: //Char Reg - //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, char_id); - break; - case 2: //Account Reg - //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, account_id); - break; - case 1: //Account2 Reg - ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); - return 0; - default: - ShowError("inter_accreg_tosql: Invalid type %d\n", type); - return 0; - - } - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) + switch( type ) + { + case 3: //Char Reg + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + Sql_ShowDebug(sql_handle); + account_id = 0; + break; + case 2: //Account Reg + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) + Sql_ShowDebug(sql_handle); + char_id = 0; + break; + case 1: //Account2 Reg + ShowError("inter_accreg_tosql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); + return 0; + default: + ShowError("inter_accreg_tosql: Invalid type %d\n", type); + return 0; } - if (reg->reg_num<=0) return 0; - - for(j=0;j<reg->reg_num;j++){ - if(reg->reg[j].str != NULL){ - sprintf(tmp_sql,"INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d','%s','%s')", - reg_db, type, type!=3?reg->account_id:0, type==3?reg->char_id:0, - jstrescapecpy(temp_str,reg->reg[j].str), jstrescapecpy(temp_str2,reg->reg[j].value)); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( reg->reg_num <= 0 ) + return 0; + + stmt = SqlStmt_Malloc(sql_handle); + if( SQL_ERROR == SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`type`, `account_id`, `char_id`, `str`, `value`) VALUES ('%d','%d','%d',?,?)", reg_db, type, account_id, char_id) ) + SqlStmt_ShowDebug(stmt); + for( i = 0; i < reg->reg_num; ++i ) + { + r = ®->reg[i]; + if( r->str[0] != '\0' && r->value != '\0' ) + { + // str + SqlStmt_BindParam(stmt, 0, SQLDT_STRING, r->str, strnlen(r->str, sizeof(r->str))); + // value + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, r->value, strnlen(r->value, sizeof(r->value))); + + if( SQL_ERROR == SqlStmt_Execute(stmt) ) + SqlStmt_ShowDebug(stmt); } } + SqlStmt_Free(stmt); return 1; } #ifndef TXT_SQL_CONVERT @@ -140,38 +146,48 @@ int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type // Load account_reg from sql (type=2) int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int type) { - int j=0; - if (reg==NULL) return 0; + struct global_reg* r; + char* data; + size_t len; + int i; + + if( reg == NULL) + return 0; + memset(reg, 0, sizeof(struct accreg)); - reg->account_id=account_id; - reg->char_id=char_id; + reg->account_id = account_id; + reg->char_id = char_id; //`global_reg_value` (`type`, `account_id`, `char_id`, `str`, `value`) - switch (type) { + switch( type ) + { case 3: //char reg - sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'",reg_db, reg->char_id); - break; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + Sql_ShowDebug(sql_handle); + break; case 2: //account reg - sprintf (tmp_sql, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'",reg_db, reg->account_id); - break; + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) + Sql_ShowDebug(sql_handle); + break; case 1: //account2 reg ShowError("inter_accreg_fromsql: Char server shouldn't handle type 1 registry values (##). That is the login server's work!\n"); return 0; + default: + ShowError("inter_accreg_fromsql: Invalid type %d\n", type); + return 0; } - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - - if (sql_res) { - for(j=0;(sql_row = mysql_fetch_row(sql_res));j++){ - strcpy(reg->reg[j].str, sql_row[0]); - strcpy(reg->reg[j].value, sql_row[1]); - } - mysql_free_result(sql_res); + for( i = 0; i < MAX_REG_NUM && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + { + r = ®->reg[i]; + // str + Sql_GetData(sql_handle, 0, &data, &len); + memcpy(r->str, data, min(len, sizeof(r->str))); + // value + Sql_GetData(sql_handle, 1, &data, &len); + memcpy(r->value, data, min(len, sizeof(r->value))); } - reg->reg_num=j; + reg->reg_num = i; + Sql_FreeResult(sql_handle); return 1; } @@ -277,18 +293,17 @@ static int inter_config_read(const char* cfgName) int inter_log(char* fmt, ...) { char str[255]; - char temp_str[510]; //Needs be twice as long as str[] //Skotlex + char esc_str[sizeof(str)*2+1];// escaped str va_list ap; + va_start(ap,fmt); + vsnprintf(str, sizeof(str), fmt, ap); + va_end(ap); - vsprintf(str,fmt,ap); - sprintf(tmp_sql,"INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')",interlog_db, jstrescapecpy(temp_str,str)); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str))); + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", interlog_db, esc_str) ) + Sql_ShowDebug(sql_handle); - va_end(ap); return 0; } @@ -298,30 +313,23 @@ int inter_log(char* fmt, ...) int inter_sql_ping(int tid, unsigned int tick, int id, int data) { ShowInfo("Pinging SQL server to keep connection alive...\n"); - mysql_ping(&mysql_handle); - if(char_gm_read) - mysql_ping(&lmysql_handle); + Sql_Ping(sql_handle); + if( char_gm_read ) + Sql_Ping(lsql_handle); return 0; } int sql_ping_init(void) { - int connection_timeout, connection_ping_interval; + 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 (!mysql_query(&mysql_handle, "SHOW VARIABLES LIKE 'wait_timeout'") - && (sql_res = mysql_store_result(&mysql_handle)) != NULL) { - sql_row = mysql_fetch_row(sql_res); - if (sql_row) - connection_timeout = atoi(sql_row[1]); - if (connection_timeout < 60) - connection_timeout = 60; - mysql_free_result(sql_res); - } + 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 @@ -342,13 +350,13 @@ int inter_init_sql(const char *file) inter_config_read(file); //DB connection initialized - mysql_init(&mysql_handle); + sql_handle = Sql_Malloc(); ShowInfo("Connect Character DB server.... (Character Server)\n"); - if(!mysql_real_connect(&mysql_handle, char_server_ip, char_server_id, char_server_pw, - char_server_db ,char_server_port, (char *)NULL, 0)) { - //pointer check - ShowFatalError("%s\n",mysql_error(&mysql_handle)); - exit(1); + if( SQL_ERROR == Sql_Connect(sql_handle, char_server_id, char_server_pw, char_server_ip, (uint16)char_server_port, char_server_db) ) + { + Sql_ShowDebug(sql_handle); + Sql_Free(sql_handle); + exit(1); } #ifndef TXT_SQL_CONVERT else if (inter_sql_test()) { @@ -356,30 +364,27 @@ int inter_init_sql(const char *file) } if(char_gm_read) { - mysql_init(&lmysql_handle); + lsql_handle = Sql_Malloc(); ShowInfo("Connect Character DB server.... (login server)\n"); - if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw, - login_server_db ,login_server_port, (char *)NULL, 0)) { - //pointer check - ShowFatalError("%s\n",mysql_error(&lmysql_handle)); - exit(1); - }else { + 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(1); + } + else + { ShowStatus ("Connect Success! (Login Server)\n"); } } #endif //TXT_SQL_CONVERT - if(strlen(default_codepage) > 0 ) { - sprintf( tmp_sql, "SET NAMES %s", default_codepage ); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( *default_codepage ) { + if( SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) ) + Sql_ShowDebug(sql_handle); #ifndef TXT_SQL_CONVERT - if(char_gm_read) - if (mysql_query(&lmysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( char_gm_read && SQL_ERROR == Sql_SetEncoding(lsql_handle, default_codepage) ) + Sql_ShowDebug(lsql_handle); #endif //TXT_SQL_CONVERT } @@ -405,32 +410,30 @@ int inter_sql_test (void) "fame", // version 1491 }; char buf[1024] = ""; + char* p; + size_t len; int i; - sprintf(tmp_sql, "EXPLAIN `%s`",char_db); - if (mysql_query(&mysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); - // store DB fields - if (sql_res) { - while((sql_row = mysql_fetch_row(sql_res))) { - strcat (buf, sql_row[0]); - strcat (buf, " "); - } - } + if( SQL_ERROR == Sql_GetColumnNames(sql_handle, char_db, buf, sizeof(buf), '\n') ) + Sql_ShowDebug(sql_handle); // check DB strings - for (i = 0; i < (int)(sizeof(fields) / sizeof(fields[0])); i++) { - if(!strstr(buf, fields[i])) { + 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(1); } } - mysql_free_result(sql_res); - return 1; } @@ -636,7 +639,11 @@ int mapif_parse_WisRequest(int fd) { struct WisData* wd; static int wisid = 0; - char name[NAME_LENGTH], t_name[NAME_LENGTH*2]; //Needs space to allocate names with escaped chars [Skotlex] + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1];// escaped name + char* data; + size_t len; + if ( fd <= 0 ) {return 0;} // check if we have a valid fd @@ -649,35 +656,37 @@ int mapif_parse_WisRequest(int fd) } memcpy(name, RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] name[NAME_LENGTH-1]= '\0'; - - sprintf (tmp_sql, "SELECT `name` FROM `%s` WHERE `name`='%s'", - char_db, jstrescapecpy(t_name, name)); - if(mysql_query(&mysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - sql_res = mysql_store_result(&mysql_handle); + + Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) + Sql_ShowDebug(sql_handle); // search if character exists before to ask all map-servers - if (!(sql_row = mysql_fetch_row(sql_res))) { + if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); - // Character exists. So, ask all map-servers - } else { + } + else + {// Character exists. So, ask all map-servers // to be sure of the correct name, rewrite it + Sql_GetData(sql_handle, 0, &data, &len); memset(name, 0, NAME_LENGTH); - strncpy(name, sql_row[0], NAME_LENGTH); + memcpy(name, data, min(len, NAME_LENGTH)); // if source is destination, don't ask other servers. - if (strcmp((char*)RFIFOP(fd,4),name) == 0) { - unsigned char buf[27]; + if( strncmp((const char*)RFIFOP(fd,4), name, NAME_LENGTH) == 0 ) + { + uint8 buf[27]; WBUFW(buf, 0) = 0x3802; memcpy(WBUFP(buf, 2), RFIFOP(fd, 4), NAME_LENGTH); WBUFB(buf,26) = 1; // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target mapif_send(fd, buf, 27); - } else { + } + else + { CREATE(wd, struct WisData, 1); @@ -695,12 +704,8 @@ int mapif_parse_WisRequest(int fd) mapif_wis_message(wd); } } - - //Freeing ... O.o - if(sql_res){ - mysql_free_result(sql_res); - } - + + Sql_FreeResult(sql_handle); return 0; } diff --git a/src/char_sql/inter.h b/src/char_sql/inter.h index 98b0fc49d..c79290c80 100644 --- a/src/char_sql/inter.h +++ b/src/char_sql/inter.h @@ -4,9 +4,8 @@ #ifndef _INTER_SQL_H_ #define _INTER_SQL_H_ -#ifndef _CBASETYPES_H_ -#include "../common/cbasetypes.h" -#endif +struct accreg; +#include "../common/sql.h" int inter_init_sql(const char *file); void inter_final(void); @@ -25,21 +24,8 @@ int inter_log(char *fmt,...); extern unsigned int party_share_level; extern char inter_log_filename[1024]; -#ifdef WIN32 -#include <winsock2.h> -#endif -//add include for DBMS(mysql) -#include <mysql.h> - -extern MYSQL mysql_handle; -extern char tmp_sql[65535]; -extern MYSQL_RES* sql_res ; -extern MYSQL_ROW sql_row ; -extern int sql_cnt; - -extern MYSQL lmysql_handle; -extern MYSQL_RES* lsql_res ; -extern MYSQL_ROW lsql_row ; +extern Sql* sql_handle; +extern Sql* lsql_handle; extern int char_server_port; extern char char_server_ip[32]; diff --git a/src/char_sql/itemdb.c b/src/char_sql/itemdb.c deleted file mode 100644 index b03d76bfe..000000000 --- a/src/char_sql/itemdb.c +++ /dev/null @@ -1,219 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "itemdb.h" -#include "db.h" -#include "inter.h" -#include "char.h" -#include "utils.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" - -#define MAX_RANDITEM 2000 - -// ** ITEMDB_OVERRIDE_NAME_VERBOSE ** -// ’è‹`‚·‚é‚ÆAitemdb.txt‚Ægrf‚Å–¼‘O‚ªˆÙ‚È‚éê‡A•\Ž¦‚µ‚Ü‚·. -//#define ITEMDB_OVERRIDE_NAME_VERBOSE 1 - -char item_db_db[256]="item_db"; // added to specify item_db sql table [Valaris] -char item_db2_db[256]="item_db2"; - -static struct dbt* item_db; - -static void* create_item(DBKey key, va_list args) { - struct item_data *id; - int nameid = key.i; - CREATE(id, struct item_data, 1); - id->nameid = nameid; - id->type = IT_ETC; - return id; -} -/*========================================== - * DB‚ÌŒŸõ - *------------------------------------------*/ -struct item_data* itemdb_search(int nameid) -{ - return idb_ensure(item_db,nameid,create_item); -} - -/*========================================== - * - *------------------------------------------*/ -int itemdb_isequip(int nameid) -{ - int type=itemdb_type(nameid); - if(type==IT_HEALING || type==IT_USABLE || type==IT_ETC || type==IT_CARD || type==IT_AMMO) - return 0; - return 1; -} -/*========================================== - * - *------------------------------------------*/ -int itemdb_isequip2(struct item_data *data) -{ - if(data) { - int type=data->type; - if(type==IT_HEALING || type==IT_USABLE || type==IT_ETC || type==IT_CARD || type==IT_AMMO) - return 0; - else - return 1; - } - return 0; -} - - - -/*========================================== - * ƒAƒCƒeƒ€ƒf[ƒ^ƒx[ƒX‚Ì“Ç‚Ýž‚Ý - *------------------------------------------*/ -static int itemdb_readdb(void) -{ - FILE *fp; - char line[1024]; - int ln=0,lines=0; - int nameid,j; - char *str[32],*p,*np; - struct item_data *id; - int i=0; - char *filename[]={ "item_db.txt","item_db2.txt" }; - - for(i=0;i<2;i++){ - sprintf(line, "%s/%s", db_path, filename[i]); - fp=fopen(line,"r"); - if(fp==NULL){ - if(i>0) - continue; - ShowFatalError("can't read %s\n",line); - exit(1); - } - - lines=0; - while(fgets(line, sizeof(line), fp)) - { - lines++; - if(line[0]=='/' && line[1]=='/') - continue; - memset(str,0,sizeof(str)); - for(j=0,np=p=line;j<4 && p;j++){ - str[j]=p; - p=strchr(p,','); - if(p){ *p++=0; np=p; } - } - if(str[0]==NULL) - continue; - - nameid=atoi(str[0]); - if(nameid<=0) - continue; - if (j < 4) - { //Crash-fix on broken item lines. [Skotlex] - ShowWarning("Reading %s: Insufficient fields for item with id %d, skipping.\n", filename[i], nameid); - continue; - } - ln++; - - //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View - id=itemdb_search(nameid); - strncpy(id->name, str[1], ITEM_NAME_LENGTH-1); - strncpy(id->jname, str[2], ITEM_NAME_LENGTH-1); - id->type=atoi(str[3]); - if (id->type == IT_DELAYCONSUME) - id->type = IT_USABLE; - } - fclose(fp); - if (ln > 0) { - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); - } - ln=0; // reset to 0 - } - return 0; -} - -static int itemdb_read_sqldb(void) // sql item_db read, shortened version of map-server item_db read [Valaris] -{ - unsigned short nameid; - struct item_data *id; - char *item_db_name[] = { item_db_db, item_db2_db }; - long unsigned int ln = 0; - int i; - - // ---------- - - for (i = 0; i < 2; i++) { - sprintf(tmp_sql, "SELECT * FROM `%s`", item_db_name[i]); - - // Execute the query; if the query execution succeeded... - if (mysql_query(&mysql_handle, tmp_sql) == 0) { - sql_res = mysql_store_result(&mysql_handle); - - // If the storage of the query result succeeded... - if (sql_res) { - // Parse each row in the query result into sql_row - while ((sql_row = mysql_fetch_row(sql_res))) - { /*Table structure is: - 00 id - 01 name_english - 02 name_japanese - 03 type - ... - */ - nameid = atoi(sql_row[0]); - - // If the identifier is not within the valid range, process the next row - if (nameid == 0) - continue; - - ln++; - - // ---------- - id=itemdb_search(nameid); - - strncpy(id->name, sql_row[1], ITEM_NAME_LENGTH-1); - strncpy(id->jname, sql_row[2], ITEM_NAME_LENGTH-1); - - id->type = atoi(sql_row[3]); - if (id->type == IT_DELAYCONSUME) - id->type = IT_USABLE; - } - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, item_db_name[i]); - ln = 0; - } else { - ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - - // Free the query result - mysql_free_result(sql_res); - } else { - ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - - return 0; -} - -/*========================================== - * - *------------------------------------------*/ -void do_final_itemdb(void) -{ - if(item_db){ - item_db->destroy(item_db,NULL); - item_db=NULL; - } -} -int do_init_itemdb(void) -{ - item_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int)); - - if (db_use_sqldbs) // it db_use_sqldbs in inter config are yes, will read from item_db for char server display [Valaris] - itemdb_read_sqldb(); - else - itemdb_readdb(); - return 0; -} diff --git a/src/char_sql/itemdb.h b/src/char_sql/itemdb.h deleted file mode 100644 index 4fbd59f96..000000000 --- a/src/char_sql/itemdb.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) Athena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _ITEMDB_H_ -#define _ITEMDB_H_ - -#include "mmo.h" - -//FIXME: Maybe it would be better to move this enum to mmo.h, -//instead of having it twice on the map server and here? [Skotlex] -enum { - IT_HEALING = 0, - IT_UNKNOWN, //1 - IT_USABLE, //2 - IT_ETC, //3 - IT_WEAPON, //4 - IT_ARMOR, //5 - IT_CARD, //6 - IT_PETEGG, //7 - IT_PETARMOR,//8 - IT_UNKNOWN2,//9 - IT_AMMO, //10 - IT_DELAYCONSUME,//11 - IT_MAX -} item_types; - -struct item_data { - int nameid; - char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH]; - int type; -}; - -extern char item_db_db[256]; -extern char item_db2_db[256]; -struct item_data* itemdb_search(int nameid); -#define itemdb_type(n) itemdb_search(n)->type - -int itemdb_isequip(int); -int itemdb_isequip2(struct item_data *); - -void do_final_itemdb(void); -int do_init_itemdb(void); - -#endif /* _ITEMDB_H_ */ diff --git a/src/common/Makefile b/src/common/Makefile.in index 258423776..c22cc721c 100644 --- a/src/common/Makefile +++ b/src/common/Makefile.in @@ -1,24 +1,62 @@ -txt sql all: obj common +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + ALL_DEPENDS=txt sql + SQL_DEPENDS=txt obj_sql common_sql +else + ALL_TARGET=txt + SQL_DEPENDS=needs_mysql +endif + +##################################################################### +.PHONY : all txt sql clean help + +all: $(ALL_DEPENDS) + +txt: obj common + +sql: $(SQL_DEPENDS) + +clean: + rm -rf *.o obj obj_sql + +help: + @echo "possible targets are 'txt' 'sql' 'all' 'clean' 'help'" + @echo "'txt' - builds object files used in txt servers" + @echo "'sql' - builds object files used in sql servers" + @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: - mkdir obj + -mkdir obj + +obj_sql: + -mkdir obj_sql common: obj/core.o obj/socket.o obj/timer.o obj/db.o obj/plugins.o obj/lock.o \ obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o \ obj/grfio.o obj/minicore.o obj/minisocket.o obj/minimalloc.o \ obj/mapindex.o obj/ers.o obj/md5calc.o +common_sql: obj_sql/sql.o + obj/%.o: %.c - $(COMPILE.c) $(OUTPUT_OPTION) $< + @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< obj/mini%.o: %.c - $(COMPILE.c) -DMINICORE $(OUTPUT_OPTION) $< + @CC@ @CFLAGS@ -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + +obj_sql/%.o: %.c + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -clean: - rm -rf *.o obj GNUmakefile - rm -rf svnversion.h HAVESVN = $(shell which svnversion) ifeq ($(findstring /,$(HAVESVN)), /) @@ -38,19 +76,20 @@ obj/minimalloc.o: malloc.c malloc.h # DO NOT DELETE obj/core.o: core.c core.h showmsg.h svnversion.h -obj/socket.o: socket.c socket.h mmo.h showmsg.h plugins.h -obj/timer.o: timer.c timer.h showmsg.h -obj/ers.o: ers.c ers.h cbasetypes.h obj/db.o: db.c db.h showmsg.h ers.h -obj/lock.o: lock.c lock.h showmsg.h +obj/ers.o: ers.c ers.h cbasetypes.h obj/grfio.o: grfio.c grfio.h -obj/nullpo.o: nullpo.c nullpo.h showmsg.h +obj/lock.o: lock.c lock.h showmsg.h obj/malloc.o: malloc.c malloc.h showmsg.h +obj/mapindex.o: mapindex.c mapindex.h +obj/md5calc.o: md5calc.c md5calc.h +obj/nullpo.o: nullpo.c nullpo.h showmsg.h obj/plugins.o: plugins.c plugins.h plugin.h obj/showmsg.o: showmsg.c showmsg.h +obj/socket.o: socket.c socket.h mmo.h showmsg.h plugins.h obj/strlib.o: strlib.c strlib.h utils.h -obj/mapindex.o: mapindex.c mapindex.h +obj/timer.o: timer.c timer.h showmsg.h obj/utils.o: utils.c utils.h malloc.h showmsg.h mmo.h -obj/md5calc.o: md5calc.c md5calc.h +obj_sql/sql.o: sql.c sql.h cbasetypes.h malloc.h showmsg.h utils.h mmo.h: cbasetypes.h @touch mmo.h diff --git a/src/common/db.c b/src/common/db.c index 80918d7f6..476c5a0c9 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -70,7 +70,6 @@ #include "db.h" #include "../common/mmo.h" -#include "../common/utils.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/ers.h" diff --git a/src/common/ers.c b/src/common/ers.c index 53c1edc3a..ecdda4609 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -40,9 +40,10 @@ \*****************************************************************************/ #include <stdlib.h> -#include "ers.h" +#include "../common/cbasetypes.h" #include "../common/malloc.h" // CREATE, RECREATE, aMalloc, aFree #include "../common/showmsg.h" // ShowMessage, ShowError, ShowFatalError, CL_BOLD, CL_NORMAL +#include "ers.h" #ifndef DISABLE_ERS /*****************************************************************************\ diff --git a/src/common/ers.h b/src/common/ers.h index 51b12d8a2..a9ba50073 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -40,7 +40,9 @@ #ifndef _ERS_H_ #define _ERS_H_ +#ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" +#endif /*****************************************************************************\ * (1) All public parts of the Entry Reusage System. * diff --git a/src/common/md5calc.c b/src/common/md5calc.c index b70236d6b..701a9db6c 100644 --- a/src/common/md5calc.c +++ b/src/common/md5calc.c @@ -173,7 +173,7 @@ void MD5_String2binary(const char * string, char * output) //Step 1.Append Padding Bits (extension of a mark bit) //1-1 - string_byte_len = strlen(string); //The byte chief of a character sequence is acquired. + string_byte_len = (unsigned int)strlen(string); //The byte chief of a character sequence is acquired. pstring = (unsigned char *)string; //The position of the present character sequence is set. //1-2 Repeat calculation until length becomes less than 64 bytes. diff --git a/src/common/mmo.h b/src/common/mmo.h index 0fcfff137..619c75295 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -4,9 +4,8 @@ #ifndef _MMO_H_ #define _MMO_H_ -#include <time.h> #include "cbasetypes.h" -#include "utils.h" // _WIN32 +#include <time.h> #define FIFOSIZE_SERVERLINK 256*1024 @@ -179,7 +178,7 @@ struct s_homunculus { //[orn] int luk ; }; -struct friend { +struct s_friend { int account_id; int char_id; char name[NAME_LENGTH]; @@ -229,7 +228,7 @@ struct mmo_charstatus { struct item inventory[MAX_INVENTORY],cart[MAX_CART]; struct skill skill[MAX_SKILL]; - struct friend friends[MAX_FRIENDS]; //New friend system [Skotlex] + struct s_friend friends[MAX_FRIENDS]; //New friend system [Skotlex] #ifdef HOTKEY_SAVING struct hotkey hotkeys[HOTKEY_SAVING]; #endif diff --git a/src/common/plugins.c b/src/common/plugins.c index a2d4de73e..58ab60b74 100644 --- a/src/common/plugins.c +++ b/src/common/plugins.c @@ -1,15 +1,15 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include "plugins.h" #include "../common/mmo.h" #include "../common/core.h" #include "../common/timer.h" -#include "../common/utils.h" +#include "../common/utils.h" // findfile() #include "../common/socket.h" #include "../common/malloc.h" #include "../common/version.h" #include "../common/showmsg.h" +#include "plugins.h" #include <stdio.h> #include <stdlib.h> diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 615b52914..6fb8a2e6c 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -2,7 +2,7 @@ // For more information, see LICENCE in the main folder #include "../common/cbasetypes.h" -#include "../common/utils.h" +#include "../common/strlib.h" // StringBuf #include "showmsg.h" #include <stdio.h> @@ -59,7 +59,7 @@ int msg_silent = 0; //Specifies how silent the console is. #define NEWBUF(buf) \ struct { \ char s_[SBUF_SIZE]; \ - struct StringBuf *d_; \ + StringBuf *d_; \ char *v_; \ int l_; \ } buf ={"",NULL,NULL,0}; \ @@ -198,7 +198,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) */ ///////////////////////////////////////////////////////////////// - unsigned long written; + DWORD written; char *p, *q; NEWBUF(tempbuf); // temporary buffer @@ -218,8 +218,8 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) p = BUFVAL(tempbuf); while ((q = strchr(p, 0x1b)) != NULL) { // find the escape character - if( 0==WriteConsole(handle, p, q-p, &written, 0) ) // write up to the escape - WriteFile(handle, p, q-p, &written, 0); + if( 0==WriteConsole(handle, p, (DWORD)(q-p), &written, 0) ) // write up to the escape + WriteFile(handle, p, (DWORD)(q-p), &written, 0); if( q[1]!='[' ) { // write the escape char (whatever purpose it has) @@ -240,7 +240,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) // skip escape and bracket q=q+2; - while(1) + for(;;) { if( ISDIGIT(*q) ) { // add number to number array, only accept 2digits, shift out the rest @@ -501,8 +501,8 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) } } if (*p) // write the rest of the buffer - if( 0==WriteConsole(handle, p, strlen(p), &written, 0) ) - WriteFile(handle,p, strlen(p), &written, 0); + if( 0==WriteConsole(handle, p, (DWORD)strlen(p), &written, 0) ) + WriteFile(handle, p, (DWORD)strlen(p), &written, 0); FREEBUF(tempbuf); return 0; } @@ -689,7 +689,10 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) ShowError("Empty string passed to _vShowMessage().\n"); return 1; } - if ((flag == MSG_DEBUG && !SHOW_DEBUG_MSG) || + if ( +#if !defined(SHOW_DEBUG_MSG) + (flag == MSG_DEBUG) || +#endif (flag == MSG_INFORMATION && msg_silent&1) || (flag == MSG_STATUS && msg_silent&2) || (flag == MSG_NOTICE && msg_silent&4) || diff --git a/src/common/socket.c b/src/common/socket.c index 221a0289b..c70c0cbaa 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -111,8 +111,9 @@ void set_defaultparse(ParseFunc defaultparse) void set_nonblocking(int fd, unsigned long yes) { // TCP_NODELAY BOOL Disables the Nagle algorithm for send coalescing. - if(MODE_NODELAY) - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof yes); +#if defined(MODE_NODELAY) && MODE_NODELAY == 1 + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&yes, sizeof yes); +#endif // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s. // The argp parameter is zero if nonblocking is to be disabled. @@ -169,7 +170,7 @@ int recv_to_fifo(int fd) if( !session_isActive(fd) ) return -1; - len = recv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, RFIFOSPACE(fd), 0); + len = recv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0); if (len == SOCKET_ERROR) { if (s_errno == S_ECONNABORTED) { @@ -203,7 +204,7 @@ int send_from_fifo(int fd) if (session[fd]->wdata_size == 0) return 0; - len = send(fd, (const char *) session[fd]->wdata, session[fd]->wdata_size, 0); + len = send(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, 0); if (len == SOCKET_ERROR) { if (s_errno == S_ECONNABORTED) { @@ -457,7 +458,7 @@ int realloc_writefifo(int fd, size_t addition) return 0; } -int RFIFOSKIP(int fd, int len) +int RFIFOSKIP(int fd, size_t len) { struct socket_data *s; @@ -477,7 +478,7 @@ int RFIFOSKIP(int fd, int len) return 0; } -int WFIFOSET(int fd, int len) +int WFIFOSET(int fd, size_t len) { size_t newreserve; struct socket_data* s = session[fd]; diff --git a/src/common/socket.h b/src/common/socket.h index 469ff678d..4015fed97 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -104,8 +104,8 @@ int make_listen_bind(uint32 ip, uint16 port); int make_connection(uint32 ip, uint16 port); int realloc_fifo(int fd, unsigned int rfifo_size, unsigned int wfifo_size); int realloc_writefifo(int fd, size_t addition); -int WFIFOSET(int fd, int len); -int RFIFOSKIP(int fd, int len); +int WFIFOSET(int fd, size_t len); +int RFIFOSKIP(int fd, size_t len); int do_sendrecv(int next); int do_parsepacket(void); diff --git a/src/common/sql.c b/src/common/sql.c new file mode 100644 index 000000000..cc6e81009 --- /dev/null +++ b/src/common/sql.c @@ -0,0 +1,851 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "sql.h" + +#ifdef WIN32 +#include <winsock2.h> +#endif +#include <mysql.h> +#include <string.h>// strlen/strnlen/memcpy/memset +#include <stdlib.h>// strtoul + + + +/// Sql handle +struct Sql +{ + StringBuf buf; + MYSQL handle; + MYSQL_RES* result; + MYSQL_ROW row; + unsigned long* lengths; +}; + + + +// Column length receiver. +// Takes care of the possible size missmatch between uint32 and unsigned long. +struct s_column_length +{ + uint32* out_length; + unsigned long length; +}; +typedef struct s_column_length s_column_length; + + + +/// Sql statement +struct SqlStmt +{ + StringBuf buf; + MYSQL_STMT* stmt; + MYSQL_BIND* params; + MYSQL_BIND* columns; + s_column_length* column_lengths; + size_t max_params; + size_t max_columns; + bool bind_params; + bool bind_columns; +}; + + + +/////////////////////////////////////////////////////////////////////////////// +// Sql Handle +/////////////////////////////////////////////////////////////////////////////// + + + +/// Allocates and initializes a new Sql handle. +Sql* Sql_Malloc(void) +{ + Sql* self; + CREATE(self, Sql, 1); + mysql_init(&self->handle); + StringBuf_Init(&self->buf); + return self; +} + + + +/// Establishes a connection. +int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db) +{ + if( self == NULL ) + return SQL_ERROR; + + StringBuf_Clear(&self->buf); + if( !mysql_real_connect(&self->handle, host, user, passwd, db, (unsigned int)port, NULL/*unix_socket*/, 0/*clientflag*/) ) + { + ShowSQL("%s\n", mysql_error(&self->handle)); + return SQL_ERROR; + } + return SQL_SUCCESS; +} + + + +/// Retrieves the timeout of the connection. +int Sql_GetTimeout(Sql* self, uint32* out_timeout) +{ + if( self && out_timeout && SQL_SUCCESS == Sql_Query(self, "SHOW VARIABLES LIKE 'wait_timeout'") ) + { + char* data; + size_t len; + if( SQL_SUCCESS == Sql_NextRow(self) && + SQL_SUCCESS == Sql_GetData(self, 1, &data, &len) ) + { + *out_timeout = (uint32)strtoul(data, NULL, 10); + Sql_FreeResult(self); + return SQL_SUCCESS; + } + Sql_FreeResult(self); + } + return SQL_ERROR; +} + + + +/// Retrieves the name of the columns of a table into out_buf, with the separator after each name. +int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep) +{ + char* data; + size_t len; + size_t off = 0; + + if( self == NULL || SQL_ERROR == Sql_Query(self, "EXPLAIN `%s`", table) ) + return SQL_ERROR; + + out_buf[off] = '\0'; + while( SQL_SUCCESS == Sql_NextRow(self) && SQL_SUCCESS == Sql_GetData(self, 0, &data, &len) ) + { + len = strnlen(data, len); + if( off + len + 2 > buf_len ) + { + ShowDebug("Sql_GetColumns: output buffer is too small\n"); + *out_buf = '\0'; + return SQL_ERROR; + } + memcpy(out_buf+off, data, len); + off += len; + out_buf[off++] = sep; + } + out_buf[off] = '\0'; + Sql_FreeResult(self); + return SQL_SUCCESS; +} + + + +/// Changes the encoding of the connection. +int Sql_SetEncoding(Sql* self, const char* encoding) +{ + return Sql_Query(self, "SET NAMES %s", encoding); +} + + + +/// Pings the connection. +int Sql_Ping(Sql* self) +{ + if( self && mysql_ping(&self->handle) == 0 ) + return SQL_SUCCESS; + return SQL_ERROR; +} + + + +/// Escapes a string. +size_t Sql_EscapeString(Sql* self, char *out_to, const char *from) +{ + if( self ) + return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)strlen(from)); + else + return (size_t)mysql_escape_string(out_to, from, (unsigned long)strlen(from)); +} + + + +/// Escapes a string. +size_t Sql_EscapeStringLen(Sql* self, char *out_to, const char *from, size_t from_len) +{ + if( self ) + return (size_t)mysql_real_escape_string(&self->handle, out_to, from, (unsigned long)from_len); + else + return (size_t)mysql_escape_string(out_to, from, (unsigned long)from_len); +} + + + +/// Executes a query. +int Sql_Query(Sql* self, const char* query, ...) +{ + int res; + va_list args; + + va_start(args, query); + res = Sql_QueryV(self, query, args); + va_end(args); + + return res; +} + + + +/// Executes a query. +int Sql_QueryV(Sql* self, const char* query, va_list args) +{ + if( self == NULL ) + return SQL_ERROR; + + Sql_FreeResult(self); + StringBuf_Clear(&self->buf); + StringBuf_Vprintf(&self->buf, query, args); + if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + { + ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + return SQL_ERROR; + } + self->result = mysql_store_result(&self->handle); + if( mysql_errno(&self->handle) != 0 ) + { + ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + return SQL_ERROR; + } + return SQL_SUCCESS; +} + + + +/// Executes a query. +int Sql_QueryStr(Sql* self, const char* query) +{ + if( self == NULL ) + return SQL_ERROR; + + Sql_FreeResult(self); + StringBuf_Clear(&self->buf); + StringBuf_AppendStr(&self->buf, query); + if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + { + ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + return SQL_ERROR; + } + self->result = mysql_store_result(&self->handle); + if( mysql_errno(&self->handle) != 0 ) + { + ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + return SQL_ERROR; + } + return SQL_SUCCESS; +} + + + +/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query. +uint64 Sql_LastInsertId(Sql* self) +{ + if( self ) + return (uint64)mysql_insert_id(&self->handle); + else + return 0; +} + + + +/// Returns the number of columns in each row of the result. +uint32 Sql_NumColumns(Sql* self) +{ + if( self && self->result ) + return (uint32)mysql_num_fields(self->result); + return 0; +} + + + +/// Returns the number of rows in the result. +uint64 Sql_NumRows(Sql* self) +{ + if( self && self->result ) + return (uint64)mysql_num_rows(self->result); + return 0; +} + + + +/// Fetches the next row. +int Sql_NextRow(Sql* self) +{ + if( self && self->result ) + { + self->row = mysql_fetch_row(self->result); + if( self->row ) + { + self->lengths = mysql_fetch_lengths(self->result); + return SQL_SUCCESS; + } + self->lengths = NULL; + if( mysql_errno(&self->handle) == 0 ) + return SQL_NO_DATA; + } + return SQL_ERROR; +} + + + +/// Gets the data of a column. +int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len) +{ + if( self && self->row ) + { + if( col < Sql_NumColumns(self) ) + { + if( out_buf ) *out_buf = self->row[col]; + if( out_len ) *out_len = (size_t)self->lengths[col]; + } + else + {// out of range - ignore + if( out_buf ) *out_buf = NULL; + if( out_len ) *out_len = 0; + } + return SQL_SUCCESS; + } + return SQL_ERROR; +} + + + +/// Frees the result of the query. +void Sql_FreeResult(Sql* self) +{ + if( self && self->result ) + { + mysql_free_result(self->result); + self->result = NULL; + self->row = NULL; + self->lengths = NULL; + } +} + + + +/// Shows debug information (last query). +void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line) +{ + if( self == NULL ) + ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); + else if( StringBuf_Length(&self->buf) > 0 ) + ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf)); + else + ShowDebug("at %s:%lu\n", debug_file, debug_line); +} + + + +/// Frees a Sql handle returned by Sql_Malloc. +void Sql_Free(Sql* self) +{ + if( self ) + { + Sql_FreeResult(self); + StringBuf_Destroy(&self->buf); + aFree(self); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +// Prepared Statements +/////////////////////////////////////////////////////////////////////////////// + + + +/// Returns the mysql integer type for the target size. +/// +/// @private +static enum enum_field_types Sql_P_SizeToMysqlIntType(int sz) +{ + switch( sz ) + { + case 1: return MYSQL_TYPE_TINY; + case 2: return MYSQL_TYPE_SHORT; + case 4: return MYSQL_TYPE_LONG; + case 8: return MYSQL_TYPE_LONGLONG; + default: + ShowDebug("SizeToMysqlIntType: unsupported size (%d)\n", sz); + return MYSQL_TYPE_NULL; + } +} + + + +/// Binds a parameter/result. +/// +/// @private +static int Sql_P_BindSqlDataType(MYSQL_BIND* bind, enum SqlDataType buffer_type, void* buffer, size_t buffer_len, unsigned long* out_length, int8* out_is_null) +{ + memset(bind, 0, sizeof(MYSQL_BIND)); + switch( buffer_type ) + { + case SQLDT_NULL: bind->buffer_type = MYSQL_TYPE_NULL; + break; + // fixed size + case SQLDT_UINT8: bind->is_unsigned = 1; + case SQLDT_INT8: bind->buffer_type = MYSQL_TYPE_TINY; + break; + case SQLDT_UINT16: bind->is_unsigned = 1; + case SQLDT_INT16: bind->buffer_type = MYSQL_TYPE_SHORT; + break; + case SQLDT_UINT32: bind->is_unsigned = 1; + case SQLDT_INT32: bind->buffer_type = MYSQL_TYPE_LONG; + break; + case SQLDT_UINT64: bind->is_unsigned = 1; + case SQLDT_INT64: bind->buffer_type = MYSQL_TYPE_LONGLONG; + break; + // platform dependent size + case SQLDT_UCHAR: bind->is_unsigned = 1; + case SQLDT_CHAR: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(char)); + break; + case SQLDT_USHORT: bind->is_unsigned = 1; + case SQLDT_SHORT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(short)); + break; + case SQLDT_UINT: bind->is_unsigned = 1; + case SQLDT_INT: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(int)); + break; + case SQLDT_ULONG: bind->is_unsigned = 1; + case SQLDT_LONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long)); + break; + case SQLDT_ULONGLONG: bind->is_unsigned = 1; + case SQLDT_LONGLONG: bind->buffer_type = Sql_P_SizeToMysqlIntType(sizeof(long long)); + break; + // floating point + case SQLDT_FLOAT: bind->buffer_type = MYSQL_TYPE_FLOAT; + break; + case SQLDT_DOUBLE: bind->buffer_type = MYSQL_TYPE_DOUBLE; + break; + // other + case SQLDT_STRING: + case SQLDT_ENUM: bind->buffer_type = MYSQL_TYPE_STRING; + break; + case SQLDT_BLOB: bind->buffer_type = MYSQL_TYPE_BLOB; + break; + default: + ShowDebug("Sql_P_BindSqlDataType: unsupported buffer type (%d)\n", buffer_type); + return SQL_ERROR; + } + bind->buffer = buffer; + bind->buffer_length = (unsigned long)buffer_len; + bind->length = out_length; + bind->is_null = (my_bool*)out_is_null; + return SQL_SUCCESS; +} + + + +/// Prints debug information about a field (type and length). +/// +/// @private +static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_types type, int is_unsigned, unsigned long length, const char* length_postfix) +{ + const char* sign = (is_unsigned ? "UNSIGNED " : ""); + const char* type_string; + switch( type ) + { + default: + ShowDebug("%stype=%s%u, length=%d\n", prefix, sign, type, length); + return; +#define SHOW_DEBUG_OF(x) case x: type_string = #x; break + SHOW_DEBUG_OF(MYSQL_TYPE_TINY); + SHOW_DEBUG_OF(MYSQL_TYPE_SHORT); + SHOW_DEBUG_OF(MYSQL_TYPE_LONG); + SHOW_DEBUG_OF(MYSQL_TYPE_INT24); + SHOW_DEBUG_OF(MYSQL_TYPE_LONGLONG); + SHOW_DEBUG_OF(MYSQL_TYPE_DECIMAL); + SHOW_DEBUG_OF(MYSQL_TYPE_FLOAT); + SHOW_DEBUG_OF(MYSQL_TYPE_DOUBLE); + SHOW_DEBUG_OF(MYSQL_TYPE_TIMESTAMP); + SHOW_DEBUG_OF(MYSQL_TYPE_DATE); + SHOW_DEBUG_OF(MYSQL_TYPE_TIME); + SHOW_DEBUG_OF(MYSQL_TYPE_DATETIME); + SHOW_DEBUG_OF(MYSQL_TYPE_YEAR); + SHOW_DEBUG_OF(MYSQL_TYPE_STRING); + SHOW_DEBUG_OF(MYSQL_TYPE_VAR_STRING); + SHOW_DEBUG_OF(MYSQL_TYPE_BLOB); + SHOW_DEBUG_OF(MYSQL_TYPE_SET); + SHOW_DEBUG_OF(MYSQL_TYPE_ENUM); + SHOW_DEBUG_OF(MYSQL_TYPE_NULL); +#undef SHOW_DEBUG_TYPE_OF + } + ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix); +} + + + +/// Allocates and initializes a new SqlStmt handle. +SqlStmt* SqlStmt_Malloc(Sql* sql) +{ + SqlStmt* self; + MYSQL_STMT* stmt; + + if( sql == NULL ) + return NULL; + + stmt = mysql_stmt_init(&sql->handle); + if( stmt == NULL ) + { + ShowSQL("DB error - %s\n", mysql_error(&sql->handle)); + return NULL; + } + CREATE(self, SqlStmt, 1); + StringBuf_Init(&self->buf); + self->stmt = stmt; + self->params = NULL; + self->columns = NULL; + self->column_lengths = NULL; + self->max_params = 0; + self->max_columns = 0; + self->bind_params = false; + self->bind_columns = false; + + return self; +} + + + +/// Prepares the statement. +int SqlStmt_Prepare(SqlStmt* self, const char* query, ...) +{ + int res; + va_list args; + + va_start(args, query); + res = SqlStmt_PrepareV(self, query, args); + va_end(args); + + return res; +} + + + +/// Prepares the statement. +int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args) +{ + if( self == NULL ) + return SQL_ERROR; + + SqlStmt_FreeResult(self); + StringBuf_Clear(&self->buf); + StringBuf_Vprintf(&self->buf, query, args); + if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + { + ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + return SQL_ERROR; + } + self->bind_params = false; + + return SQL_SUCCESS; +} + + + +/// Prepares the statement. +int SqlStmt_PrepareStr(SqlStmt* self, const char* query) +{ + if( self == NULL ) + return SQL_ERROR; + + SqlStmt_FreeResult(self); + StringBuf_Clear(&self->buf); + StringBuf_AppendStr(&self->buf, query); + if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + { + ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + return SQL_ERROR; + } + self->bind_params = false; + + return SQL_SUCCESS; +} + + + +/// Returns the number of parameters in the prepared statement. +size_t SqlStmt_NumParams(SqlStmt* self) +{ + if( self ) + return (size_t)mysql_stmt_param_count(self->stmt); + else + return 0; +} + + + +/// Binds a parameter to a buffer. +int SqlStmt_BindParam(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, void* buffer, size_t buffer_len) +{ + if( self == NULL ) + return SQL_ERROR; + + if( !self->bind_params ) + {// initialize the bindings + size_t i; + size_t count; + + count = SqlStmt_NumParams(self); + if( self->max_params < count ) + { + self->max_params = count; + RECREATE(self->params, MYSQL_BIND, count); + } + memset(self->params, 0, count*sizeof(MYSQL_BIND)); + for( i = 0; i < count; ++i ) + self->params[i].buffer_type = MYSQL_TYPE_NULL; + self->bind_params = true; + } + if( idx < self->max_params ) + return Sql_P_BindSqlDataType(self->params+idx, buffer_type, buffer, buffer_len, NULL, NULL); + else + return SQL_SUCCESS;// out of range - ignore +} + + + +/// Executes the prepared statement. +int SqlStmt_Execute(SqlStmt* self) +{ + if( self == NULL ) + return SQL_ERROR; + + SqlStmt_FreeResult(self); + if( (self->bind_params && mysql_stmt_bind_param(self->stmt, self->params)) || + mysql_stmt_execute(self->stmt) ) + { + ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + return SQL_ERROR; + } + self->bind_columns = false; + if( mysql_stmt_store_result(self->stmt) )// store all the data + { + ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + return SQL_ERROR; + } + + return SQL_SUCCESS; +} + + + +/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement. +uint64 SqlStmt_LastInsertId(SqlStmt* self) +{ + if( self ) + return (uint64)mysql_stmt_insert_id(self->stmt); + else + return 0; +} + + + +/// Returns the number of columns in each row of the result. +size_t SqlStmt_NumColumns(SqlStmt* self) +{ + if( self ) + return (size_t)mysql_stmt_field_count(self->stmt); + else + return 0; +} + + + +/// Binds the result of a column to a buffer. +int SqlStmt_BindColumn(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null) +{ + if( self == NULL ) + return SQL_ERROR; + + if( buffer_type == SQLDT_STRING || buffer_type == SQLDT_ENUM ) + { + if( buffer_len < 1 ) + { + ShowDebug("SqlStmt_BindColumn: buffer_len(%d) is too small, no room for the nul-terminator\n", buffer_len); + return SQL_ERROR; + } + --buffer_len;// nul-terminator + } + if( !self->bind_columns ) + {// initialize the bindings + size_t i; + size_t cols; + + cols = SqlStmt_NumColumns(self); + if( self->max_columns < cols ) + { + self->max_columns = cols; + RECREATE(self->columns, MYSQL_BIND, cols); + RECREATE(self->column_lengths, s_column_length, cols); + } + memset(self->columns, 0, cols*sizeof(MYSQL_BIND)); + memset(self->column_lengths, 0, cols*sizeof(s_column_length)); + for( i = 0; i < cols; ++i ) + self->columns[i].buffer_type = MYSQL_TYPE_NULL; + self->bind_columns = true; + } + if( idx < self->max_columns ) + { + self->column_lengths[idx].out_length = out_length; + return Sql_P_BindSqlDataType(self->columns+idx, buffer_type, buffer, buffer_len, &self->column_lengths[idx].length, out_is_null); + } + else + { + return SQL_SUCCESS;// out of range - ignore + } +} + + + +/// Returns the number of rows in the result. +uint64 SqlStmt_NumRows(SqlStmt* self) +{ + if( self ) + return (uint64)mysql_stmt_num_rows(self->stmt); + else + return 0; +} + + + +/// Fetches the next row. +int SqlStmt_NextRow(SqlStmt* self) +{ + int err; + size_t i; + size_t cols; + MYSQL_BIND* column; + unsigned long length; + + if( self == NULL ) + return SQL_ERROR; + + // bind columns + if( self->bind_columns && mysql_stmt_bind_result(self->stmt, self->columns) ) + err = 1;// error binding columns + else + err = mysql_stmt_fetch(self->stmt);// fetch row + + // check for errors + if( err == MYSQL_NO_DATA ) + return SQL_NO_DATA; + if( err == MYSQL_DATA_TRUNCATED ) + { + my_bool truncated; + + if( !self->bind_columns ) + { + ShowSQL("DB error - data truncated (unknown source, columns are not bound)\n"); + return SQL_ERROR; + } + + // find truncated column + cols = SqlStmt_NumColumns(self); + for( i = 0; i < cols; ++i ) + { + column = &self->columns[i]; + column->error = &truncated; + mysql_stmt_fetch_column(self->stmt, column, (unsigned int)i, 0); + column->error = NULL; + if( truncated ) + {// report truncated column + MYSQL_RES* meta; + MYSQL_FIELD* field; + + meta = mysql_stmt_result_metadata(self->stmt); + field = mysql_fetch_field_direct(meta, (unsigned int)i); + ShowSQL("DB error - data of field '%s' was truncated.\n", field->name); + ShowDebug("column - %lu\n", (unsigned long)i); + Sql_P_ShowDebugMysqlFieldInfo("data - ", field->type, field->flags&UNSIGNED_FLAG, self->column_lengths[i].length, ""); + if( column->buffer_type == MYSQL_TYPE_STRING ) + Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "+1(nul-terminator)"); + else + Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, ""); + mysql_free_result(meta); + return SQL_ERROR; + } + } + ShowSQL("DB error - data truncated (unknown source)\n"); + return SQL_ERROR; + } + if( err ) + { + ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + return SQL_ERROR; + } + + // propagate column lengths and clear unused parts of string/enum/blob buffers + cols = SqlStmt_NumColumns(self); + for( i = 0; i < cols; ++i ) + { + length = self->column_lengths[i].length; + if( self->column_lengths[i].out_length ) + *self->column_lengths[i].out_length = (uint32)length; + column = &self->columns[i]; + if( column->buffer_type == MYSQL_TYPE_STRING ) + {// clear unused part of the string/enum buffer (and nul-terminate) + memset((char*)column->buffer + length, 0, column->buffer_length - length + 1); + } + else if( column->buffer_type == MYSQL_TYPE_BLOB && length < column->buffer_length ) + {// clear unused part of the blob buffer + memset((char*)column->buffer + length, 0, column->buffer_length - length); + } + } + + return SQL_SUCCESS; +} + + + +/// Frees the result of the statement execution. +void SqlStmt_FreeResult(SqlStmt* self) +{ + if( self ) + mysql_stmt_free_result(self->stmt); +} + + + +/// Shows debug information (with statement). +void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line) +{ + if( self == NULL ) + ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); + if( StringBuf_Length(&self->buf) > 0 ) + ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf)); + else + ShowDebug("at %s:%lu\n", debug_file, debug_line); +} + + + +/// Frees a SqlStmt returned by SqlStmt_Malloc. +void SqlStmt_Free(SqlStmt* self) +{ + if( self ) + { + SqlStmt_FreeResult(self); + StringBuf_Destroy(&self->buf); + mysql_stmt_close(self->stmt); + if( self->params ) + aFree(self->params); + if( self->columns ) + { + aFree(self->columns); + aFree(self->column_lengths); + } + aFree(self); + } +} diff --git a/src/common/sql.h b/src/common/sql.h new file mode 100644 index 000000000..ef76b2ec5 --- /dev/null +++ b/src/common/sql.h @@ -0,0 +1,343 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _COMMON_SQL_H_ +#define _COMMON_SQL_H_ + +#ifndef _CBASETYPES_H_ +#include "../common/cbasetypes.h" +#endif +#include <stdarg.h>// va_list + + + +// Return codes +#define SQL_ERROR -1 +#define SQL_SUCCESS 0 +#define SQL_NO_DATA 100 + + + +/// Data type identifier. +/// String, enum and blob data types need the buffer length specified. +enum SqlDataType +{ + SQLDT_NULL, + // fixed size + SQLDT_INT8, + SQLDT_INT16, + SQLDT_INT32, + SQLDT_INT64, + SQLDT_UINT8, + SQLDT_UINT16, + SQLDT_UINT32, + SQLDT_UINT64, + // platform dependent size + SQLDT_CHAR, + SQLDT_SHORT, + SQLDT_INT, + SQLDT_LONG, + SQLDT_LONGLONG, + SQLDT_UCHAR, + SQLDT_USHORT, + SQLDT_UINT, + SQLDT_ULONG, + SQLDT_ULONGLONG, + // floating point + SQLDT_FLOAT, + SQLDT_DOUBLE, + // other + SQLDT_STRING, + SQLDT_ENUM, + // Note: An ENUM is a string with restricted values. When an invalid value + // is inserted, it is saved as an empty string (numerical value 0). + SQLDT_BLOB, + SQLDT_LASTID +}; + +struct Sql;// Sql handle (private access) +struct SqlStmt;// Sql statement (private access) + +typedef enum SqlDataType SqlDataType; +typedef struct Sql Sql; +typedef struct SqlStmt SqlStmt; + + +/// Allocates and initializes a new Sql handle. +struct Sql* Sql_Malloc(void); + + + +/// Establishes a connection. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db); + + + + +/// Retrieves the timeout of the connection. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_GetTimeout(Sql* self, uint32* out_timeout); + + + + +/// Retrieves the name of the columns of a table into out_buf, with the separator after each name. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep); + + + + +/// Changes the encoding of the connection. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_SetEncoding(Sql* self, const char* encoding); + + + +/// Pings the connection. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_Ping(Sql* self); + + + +/// Escapes a string. +/// The output buffer must be at least strlen(from)*2+1 in size. +/// +/// @return The size of the escaped string +size_t Sql_EscapeString(Sql* self, char* out_to, const char* from); + + + +/// Escapes a string. +/// The output buffer must be at least from_len*2+1 in size. +/// +/// @return The size of the escaped string +size_t Sql_EscapeStringLen(Sql* self, char* out_to, const char* from, size_t from_len); + + + +/// Executes a query. +/// Any previous result is freed. +/// The query is constructed as if it was sprintf. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_Query(Sql* self, const char* query, ...); + + + +/// Executes a query. +/// Any previous result is freed. +/// The query is constructed as if it was svprintf. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_QueryV(Sql* self, const char* query, va_list args); + + + +/// Executes a query. +/// Any previous result is freed. +/// The query is used directly. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_QueryStr(Sql* self, const char* query); + + + +/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query. +/// +/// @return Value of the auto-increment column +uint64 Sql_LastInsertId(Sql* self); + + + +/// Returns the number of columns in each row of the result. +/// +/// @return Number of columns +uint32 Sql_NumColumns(Sql* self); + + + +/// Returns the number of rows in the result. +/// +/// @return Number of rows +uint64 Sql_NumRows(Sql* self); + + + +/// Fetches the next row. +/// The data of the previous row is no longer valid. +/// +/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA +int Sql_NextRow(Sql* self); + + + +/// Gets the data of a column. +/// The data remains valid until the next row is fetched or the result is freed. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len); + + + +/// Frees the result of the query. +void Sql_FreeResult(Sql* self); + + + +#if defined(SQL_REMOVE_SHOWDEBUG) +#define Sql_ShowDebug(self) (void)0 +#else +#define Sql_ShowDebug(self) Sql_ShowDebug_(self, __FILE__, __LINE__) +#endif +/// Shows debug information (last query). +void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line); + + + +/// Frees a Sql handle returned by Sql_Malloc. +void Sql_Free(Sql* self); + + + +/////////////////////////////////////////////////////////////////////////////// +// Prepared Statements +/////////////////////////////////////////////////////////////////////////////// +// Parameters are placed in the statement by embedding question mark ('?') +// characters into the query at the appropriate positions. +// The markers are legal only in places where they represent data. +// The markers cannot be inside quotes. Quotes will be added automatically +// when they are required. +// +// example queries with parameters: +// 1) SELECT col FROM table WHERE id=? +// 2) INSERT INTO table(col1,col2) VALUES(?,?) + + + +/// Allocates and initializes a new SqlStmt handle. +/// It uses the connection of the parent Sql handle. +/// Queries in Sql and SqlStmt are independent and don't affect each other. +/// +/// @return SqlStmt handle or NULL if an error occured +struct SqlStmt* SqlStmt_Malloc(Sql* sql); + + + +/// Prepares the statement. +/// Any previous result is freed and all parameter bindings are removed. +/// The query is constructed as if it was sprintf. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_Prepare(SqlStmt* self, const char* query, ...); + + + +/// Prepares the statement. +/// Any previous result is freed and all parameter bindings are removed. +/// The query is constructed as if it was svprintf. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args); + + + +/// Prepares the statement. +/// Any previous result is freed and all parameter bindings are removed. +/// The query is used directly. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_PrepareStr(SqlStmt* self, const char* query); + + + +/// Returns the number of parameters in the prepared statement. +/// +/// @return Number or paramenters +size_t SqlStmt_NumParams(SqlStmt* self); + + + +/// Binds a parameter to a buffer. +/// The buffer data will be used when the statement is executed. +/// All parameters should have bindings. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_BindParam(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len); + + + +/// Executes the prepared statement. +/// Any previous result is freed and all column bindings are removed. +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_Execute(SqlStmt* self); + + + +/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE statement. +/// +/// @return Value of the auto-increment column +uint64 SqlStmt_LastInsertId(SqlStmt* self); + + + +/// Returns the number of columns in each row of the result. +/// +/// @return Number of columns +size_t SqlStmt_NumColumns(SqlStmt* self); + + + +/// Binds the result of a column to a buffer. +/// The buffer will be filled with data when the next row is fetched. +/// For string/enum buffer types there has to be enough space for the data +/// and the nul-terminator (an extra byte). +/// +/// @return SQL_SUCCESS or SQL_ERROR +int SqlStmt_BindColumn(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null); + + + +/// Returns the number of rows in the result. +/// +/// @return Number of rows +uint64 SqlStmt_NumRows(SqlStmt* self); + + + +/// Fetches the next row. +/// All column bindings will be filled with data. +/// +/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA +int SqlStmt_NextRow(SqlStmt* self); + + + +/// Frees the result of the statement execution. +void SqlStmt_FreeResult(SqlStmt* self); + + + +#if defined(SQL_REMOVE_SHOWDEBUG) +#define SqlStmt_ShowDebug(self) (void)0 +#else +#define SqlStmt_ShowDebug(self) SqlStmt_ShowDebug_(self, __FILE__, __LINE__) +#endif +/// Shows debug information (with statement). +void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line); + + + +/// Frees a SqlStmt returned by SqlStmt_Malloc. +void SqlStmt_Free(SqlStmt* self); + + + +#endif /* _COMMON_SQL_H_ */ diff --git a/src/common/strlib.c b/src/common/strlib.c index a683dc100..4f204a768 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -3,7 +3,6 @@ #include "../common/cbasetypes.h" #include "../common/malloc.h" -#include "../common/utils.h" #include "strlib.h" #include <stdio.h> @@ -258,7 +257,7 @@ int e_mail_check(char* email) { char ch; char* last_arobas; - int len = strlen(email); + size_t len = strlen(email); // athena limits if (len < 3 || len > 39) @@ -310,3 +309,134 @@ char* safestrncpy(char* dst, const char* src, size_t n) ret[n - 1] = '\0'; return ret; } + + +///////////////////////////////////////////////////////////////////// +// StringBuf - dynamic string +// +// @author MouseJstr (original) + +/// Allocates a StringBuf +StringBuf* StringBuf_Malloc() +{ + StringBuf* self; + CREATE(self, StringBuf, 1); + StringBuf_Init(self); + return self; +} + +/// Initializes a previously allocated StringBuf +void StringBuf_Init(StringBuf* self) +{ + self->max_ = 1024; + self->ptr_ = self->buf_ = (char*)aMallocA(self->max_ + 1); +} + +/// Appends the result of printf to the StringBuf +int StringBuf_Printf(StringBuf* self, const char* fmt, ...) +{ + int len; + va_list ap; + + va_start(ap, fmt); + len = StringBuf_Vprintf(self, fmt, ap); + va_end(ap); + + return len; +} + +/// Appends the result of vprintf to the StringBuf +int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap) +{ + int n, size, off; + + for(;;) + { + /* Try to print in the allocated space. */ + size = self->max_ - (self->ptr_ - self->buf_); + n = vsnprintf(self->ptr_, size, fmt, ap); + /* If that worked, return the length. */ + if( n > -1 && n < size ) + { + self->ptr_ += n; + return (int)(self->ptr_ - self->buf_); + } + /* Else try again with more space. */ + self->max_ *= 2; // twice the old size + off = (int)(self->ptr_ - self->buf_); + self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1); + self->ptr_ = self->buf_ + off; + } +} + +/// Appends the contents of another StringBuf to the StringBuf +int StringBuf_Append(StringBuf* self, const StringBuf* sbuf) +{ + int available = self->max_ - (self->ptr_ - self->buf_); + int needed = (int)(sbuf->ptr_ - sbuf->buf_); + + if( needed >= available ) + { + int off = (int)(self->ptr_ - self->buf_); + self->max_ += needed; + self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1); + self->ptr_ = self->buf_ + off; + } + + memcpy(self->ptr_, sbuf->buf_, needed); + self->ptr_ += needed; + return (int)(self->ptr_ - self->buf_); +} + +// Appends str to the StringBuf +int StringBuf_AppendStr(StringBuf* self, const char* str) +{ + int available = self->max_ - (self->ptr_ - self->buf_); + int needed = (int)strlen(str); + + if( needed >= available ) + {// not enough space, expand the buffer (minimum expansion = 1024) + int off = (int)(self->ptr_ - self->buf_); + self->max_ += max(needed, 1024); + self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1); + self->ptr_ = self->buf_ + off; + } + + memcpy(self->ptr_, str, needed); + self->ptr_ += needed; + return (int)(self->ptr_ - self->buf_); +} + +// Returns the length of the data in the Stringbuf +int StringBuf_Length(StringBuf* self) +{ + return (int)(self->ptr_ - self->buf_); +} + +/// Returns the data in the StringBuf +char* StringBuf_Value(StringBuf* self) +{ + *self->ptr_ = '\0'; + return self->buf_; +} + +/// Clears the contents of the StringBuf +void StringBuf_Clear(StringBuf* self) +{ + self->ptr_ = self->buf_; +} + +/// Destroys the StringBuf +void StringBuf_Destroy(StringBuf* self) +{ + aFree(self->buf_); + self->ptr_ = self->buf_ = 0; + self->max_ = 0; +} + +// Frees a StringBuf returned by StringBuf_Malloc +void StringBuf_Free(StringBuf* self) +{ + StringBuf_Destroy(self); + aFree(self); +} diff --git a/src/common/strlib.h b/src/common/strlib.h index 42fb75ab2..ee473f466 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -7,6 +7,7 @@ #ifndef _CBASETYPES_H_ #include "../common/cbasetypes.h" #endif +#include <stdarg.h> char* jstrescape (char* pt); char* jstrescapecpy (char* pt, const char* spt); @@ -33,4 +34,25 @@ int config_switch(const char* str); /// always nul-terminates the string char* safestrncpy(char* dst, const char* src, size_t n); +/// StringBuf - dynamic string +struct StringBuf +{ + char *buf_; + char *ptr_; + unsigned int max_; +}; +typedef struct StringBuf StringBuf; + +StringBuf* StringBuf_Malloc(void); +void StringBuf_Init(StringBuf* self); +int StringBuf_Printf(StringBuf* self, const char* fmt, ...); +int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list args); +int StringBuf_Append(StringBuf* self, const StringBuf *sbuf); +int StringBuf_AppendStr(StringBuf* self, const char* str); +int StringBuf_Length(StringBuf* self); +char* StringBuf_Value(StringBuf* self); +void StringBuf_Clear(StringBuf* self); +void StringBuf_Destroy(StringBuf* self); +void StringBuf_Free(StringBuf* self); + #endif /* _STRLIB_H_ */ diff --git a/src/common/utils.c b/src/common/utils.c index 15d1d2e68..354bd3814 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -55,118 +55,6 @@ void dump(FILE* fp, const unsigned char* buffer, int length) fprintf(fp, "\n"); } -// Allocate a StringBuf [MouseJstr] -struct StringBuf * StringBuf_Malloc() -{ - struct StringBuf * ret = (struct StringBuf *) aMallocA(sizeof(struct StringBuf)); - StringBuf_Init(ret); - return ret; -} - -// Initialize a previously allocated StringBuf [MouseJstr] -void StringBuf_Init(struct StringBuf * sbuf) { - sbuf->max_ = 1024; - sbuf->ptr_ = sbuf->buf_ = (char *) aMallocA(sbuf->max_ + 1); -} - -// vprintf into a StringBuf, moving the pointer [MouseJstr] -int StringBuf_Vprintf(struct StringBuf *sbuf,const char *fmt,va_list ap) -{ - int n, size, off; - - while (1) { - /* Try to print in the allocated space. */ - size = sbuf->max_ - (sbuf->ptr_ - sbuf->buf_); - n = vsnprintf (sbuf->ptr_, size, fmt, ap); - /* If that worked, return the length. */ - if (n > -1 && n < size) { - sbuf->ptr_ += n; - return (int)(sbuf->ptr_ - sbuf->buf_); - } - /* Else try again with more space. */ - sbuf->max_ *= 2; // twice the old size - off = (int)(sbuf->ptr_ - sbuf->buf_); - sbuf->buf_ = (char *) aRealloc(sbuf->buf_, sbuf->max_ + 1); - sbuf->ptr_ = sbuf->buf_ + off; - } -} - -// printf into a StringBuf, moving the pointer [MouseJstr] -int StringBuf_Printf(struct StringBuf *sbuf,const char *fmt,...) -{ - int len; - va_list ap; - - va_start(ap,fmt); - len = StringBuf_Vprintf(sbuf,fmt,ap); - va_end(ap); - - return len; -} - -// Append buf2 onto the end of buf1 [MouseJstr] -int StringBuf_Append(struct StringBuf *buf1,const struct StringBuf *buf2) -{ - int buf1_avail = buf1->max_ - (buf1->ptr_ - buf1->buf_); - int size2 = (int)(buf2->ptr_ - buf2->buf_); - - if (size2 >= buf1_avail) { - int off = (int)(buf1->ptr_ - buf1->buf_); - buf1->max_ += size2; - buf1->buf_ = (char *) aRealloc(buf1->buf_, buf1->max_ + 1); - buf1->ptr_ = buf1->buf_ + off; - } - - memcpy(buf1->ptr_, buf2->buf_, size2); - buf1->ptr_ += size2; - return (int)(buf1->ptr_ - buf1->buf_); -} - -// Appends str onto the end of buf -int StringBuf_AppendStr(struct StringBuf* sbuf, const char* str) -{ - int available = sbuf->max_ - (sbuf->ptr_ - sbuf->buf_); - int size = (int)strlen(str); - - if( size >= available ) - {// not enough space, expand the buffer (minimum expansion = 1024) - int off = (int)(sbuf->ptr_ - sbuf->buf_); - sbuf->max_ += max(size, 1024); - sbuf->buf_ = (char *) aRealloc(sbuf->buf_, sbuf->max_ + 1); - sbuf->ptr_ = sbuf->buf_ + off; - } - - memcpy(sbuf->ptr_, str, size); - sbuf->ptr_ += size; - return (int)(sbuf->ptr_ - sbuf->buf_); -} - -// Returns the length of the data in a Stringbuf -int StringBuf_Length(struct StringBuf *sbuf) -{ - return (int)(sbuf->ptr_ - sbuf->buf_); -} - -// Destroy a StringBuf [MouseJstr] -void StringBuf_Destroy(struct StringBuf *sbuf) -{ - aFree(sbuf->buf_); - sbuf->ptr_ = sbuf->buf_ = 0; -} - -// Free a StringBuf returned by StringBuf_Malloc [MouseJstr] -void StringBuf_Free(struct StringBuf *sbuf) -{ - StringBuf_Destroy(sbuf); - aFree(sbuf); -} - -// Return the built string from the StringBuf [MouseJstr] -char * StringBuf_Value(struct StringBuf *sbuf) -{ - *sbuf->ptr_ = '\0'; - return sbuf->buf_; -} #ifdef WIN32 @@ -293,35 +181,43 @@ void findfile(const char *p, const char *pat, void (func)(const char*)) } #endif -uint8 GetByte(uint32 val, size_t num) +uint8 GetByte(uint32 val, int idx) { - switch( num ) + switch( idx ) { - case 0: return (uint8)((val & 0x000000FF) ); - case 1: return (uint8)((val & 0x0000FF00) >> 0x08); - case 2: return (uint8)((val & 0x00FF0000) >> 0x10); - case 3: return (uint8)((val & 0xFF000000) >> 0x18); - default: return 0; //better throw something here + case 0: return (uint8)( (val & 0x000000FF) ); + case 1: return (uint8)( (val & 0x0000FF00) >> 0x08 ); + case 2: return (uint8)( (val & 0x00FF0000) >> 0x10 ); + case 3: return (uint8)( (val & 0xFF000000) >> 0x18 ); + default: +#if defined(DEBUG) + ShowDebug("GetByte: invalid index (idx=%d)\n", idx); +#endif + return 0; } } -uint16 GetWord(uint32 val, size_t num) + +uint16 GetWord(uint32 val, int idx) { - switch( num ) + switch( idx ) { - case 0: return (uint16)((val & 0x0000FFFF) ); - case 1: return (uint16)((val & 0xFFFF0000) >> 0x10); - default: return 0; //better throw something here + case 0: return (uint16)( (val & 0x0000FFFF) ); + case 1: return (uint16)( (val & 0xFFFF0000) >> 0x10 ); + default: +#if defined(DEBUG) + ShowDebug("GetWord: invalid index (idx=%d)\n", idx); +#endif + return 0; } } uint16 MakeWord(uint8 byte0, uint8 byte1) { - return - ((uint16)(byte0 ))| - ((uint16)(byte1 << 0x08)); + return byte0 | (byte1 << 0x08); } + uint32 MakeDWord(uint16 word0, uint16 word1) { return - ((uint32)(word0 ))| - ((uint32)(word1 << 0x10)); + ( (uint32)(word0 ) )| + ( (uint32)(word1 << 0x10) ); } diff --git a/src/common/utils.h b/src/common/utils.h index 898a63ab4..21e8e090c 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -4,29 +4,15 @@ #ifndef _UTILS_H_ #define _UTILS_H_ -#include <stdio.h> -#include <stdarg.h> +#ifndef _CBASETYPES_H_ +#include "../common/cbasetypes.h" +#endif + +#include <stdio.h> // FILE* // generate a hex dump of the first 'length' bytes of 'buffer' void dump(FILE* fp, const unsigned char* buffer, int length); -struct StringBuf { - char *buf_; - char *ptr_; - unsigned int max_; -}; - -struct StringBuf * StringBuf_Malloc(void); -void StringBuf_Init(struct StringBuf *); -int StringBuf_Vprintf(struct StringBuf *,const char *,va_list); -int StringBuf_Printf(struct StringBuf *,const char *,...); -int StringBuf_Append(struct StringBuf *,const struct StringBuf *); -int StringBuf_AppendStr(struct StringBuf* sbuf, const char* str); -int StringBuf_Length(struct StringBuf* sbuf); -char * StringBuf_Value(struct StringBuf *); -void StringBuf_Destroy(struct StringBuf *); -void StringBuf_Free(struct StringBuf *); - void findfile(const char *p, const char *pat, void (func)(const char*)); //Caps values to min/max @@ -36,8 +22,8 @@ void findfile(const char *p, const char *pat, void (func)(const char*)); // byte word dword access [Shinomori] ////////////////////////////////////////////////////////////////////////// -extern uint8 GetByte(uint32 val, size_t num); -extern uint16 GetWord(uint32 val, size_t num); +extern uint8 GetByte(uint32 val, int idx); +extern uint16 GetWord(uint32 val, int idx); extern uint16 MakeWord(uint8 byte0, uint8 byte1); extern uint32 MakeDWord(uint16 word0, uint16 word1); diff --git a/src/ladmin/Makefile b/src/ladmin/Makefile deleted file mode 100644 index c5818404b..000000000 --- a/src/ladmin/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -all txt sql: ladmin - -COMMON_OBJ = ../common/obj/minicore.o ../common/obj/minisocket.o ../common/obj/timer.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o \ - ../common/obj/utils.o ../common/obj/md5calc.o -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ - ../common/version.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h \ - ../common/utils.h ../common/md5calc.h - -ladmin: ladmin.o $(COMMON_OBJ) - $(CC) -o ../../$@ ladmin.o $(COMMON_OBJ) $(LIB_S) - -clean: - rm -f *.o ../../ladmin GNUmakefile - -# DO NOT DELETE - -ladmin.o: ladmin.c ladmin.h $(COMMON_H) diff --git a/src/ladmin/Makefile.in b/src/ladmin/Makefile.in new file mode 100644 index 000000000..f1f7bff23 --- /dev/null +++ b/src/ladmin/Makefile.in @@ -0,0 +1,31 @@ +COMMON_OBJ = ../common/obj/minicore.o ../common/obj/minisocket.o ../common/obj/timer.o \ + ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o \ + ../common/obj/utils.o ../common/obj/md5calc.o +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ + ../common/version.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h \ + ../common/utils.h ../common/md5calc.h + +##################################################################### +.PHONY : all ladmin clean help + +all: ladmin + +ladmin: ladmin.o $(COMMON_OBJ) + @CC@ @LDFLAGS@ -o ../../ladmin@EXEEXT@ ladmin.o $(COMMON_OBJ) @LIBS@ + +clean: + rm -f *.o ../../ladmin@EXEEXT@ + +help: + @echo "possible targets are 'ladmin' 'all' 'clean' 'help'" + @echo "'ladmin' - remote administration tool" + @echo "'all' - builds all above targets" + @echo "'clean' - cleans builds and objects" + @echo "'help' - outputs this message" + +##################################################################### + +# DO NOT DELETE + +ladmin.o: ladmin.c ladmin.h $(COMMON_H) + @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< diff --git a/src/login/Makefile b/src/login/Makefile deleted file mode 100644 index 11d2e165f..000000000 --- a/src/login/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -all txt: login-server - -COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ - ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ - ../common/obj/strlib.o ../common/obj/grfio.o \ - ../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/md5calc.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/md5calc.h - -%.o: %.c - $(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $< - -login-server: login.o $(COMMON_OBJ) - $(CC) -o ../../$@ login.o $(COMMON_OBJ) $(LIB_S) - -clean: - rm -f *.o ../../login-server GNUmakefile - -# DO NOT DELETE - -login.o: login.c login.h $(COMMON_H) diff --git a/src/login/Makefile.in b/src/login/Makefile.in new file mode 100644 index 000000000..c0fdcc8e3 --- /dev/null +++ b/src/login/Makefile.in @@ -0,0 +1,35 @@ +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ + ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ + ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ + ../common/obj/strlib.o ../common/obj/grfio.o ../common/obj/mapindex.o \ + ../common/obj/ers.o ../common/obj/md5calc.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 + +##################################################################### +.PHONY : all login-server clean help + +all: login-server + +login-server: login.o $(COMMON_OBJ) + @CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ login.o $(COMMON_OBJ) @LIBS@ + +clean: + rm -f *.o ../../login-server@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" + +##################################################################### + +# DO NOT DELETE + +login.o: login.c login.h $(COMMON_H) + @CC@ @CFLAGS@ -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< diff --git a/src/login/login.c b/src/login/login.c index 970bf3aab..bacab0894 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -2,6 +2,7 @@ // 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" @@ -9,7 +10,6 @@ #include "../common/lock.h" #include "../common/malloc.h" #include "../common/strlib.h" -#include "../common/mmo.h" #include "../common/showmsg.h" #include "../common/version.h" #include "../common/md5calc.h" @@ -17,10 +17,8 @@ #include <stdio.h> #include <stdlib.h> -#include <sys/stat.h> // for stat/lstat/fstat -#include <signal.h> -#include <fcntl.h> #include <string.h> +#include <sys/stat.h> // for stat/lstat/fstat uint32 account_id_count = START_ACCOUNT_NUM; bool new_account_flag = true; @@ -1092,20 +1090,18 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email) account_id_count++; auth_dat[i].account_id = account_id_count++; - strncpy(auth_dat[i].userid, account->userid, NAME_LENGTH); auth_dat[i].userid[23] = '\0'; - if (use_md5_passwds) { + safestrncpy(auth_dat[i].userid, account->userid, NAME_LENGTH); + if( use_md5_passwds ) MD5_String(account->passwd, auth_dat[i].pass); - } else { - strncpy(auth_dat[i].pass, account->passwd, NAME_LENGTH); auth_dat[i].pass[23] = '\0'; - } - memcpy(auth_dat[i].lastlogin, "-", 2); + else + safestrncpy(auth_dat[i].pass, account->passwd, NAME_LENGTH); + safestrncpy(auth_dat[i].lastlogin, "-", sizeof(auth_dat[i].lastlogin)); auth_dat[i].sex = (sex == 'M' || sex == 'm'); auth_dat[i].logincount = 0; auth_dat[i].state = 0; - strncpy(auth_dat[i].email, e_mail_check(email) ? email : "a@a.com", 40); - strncpy(auth_dat[i].error_message, "-", 20); + safestrncpy(auth_dat[i].email, e_mail_check(email) ? email : "a@a.com", sizeof(auth_dat[i].email)); + safestrncpy(auth_dat[i].error_message, "-", sizeof(auth_dat[i].error_message)); auth_dat[i].ban_until_time = 0; - if (start_limited_time < 0) auth_dat[i].connect_until_time = 0; // unlimited else { // limited time @@ -1128,9 +1124,9 @@ int mmo_auth_new(struct mmo_account* account, char sex, char* email) return (account_id_count - 1); } -//--------------------------------------- +//----------------------------------------------------- // Check/authentication of a connection -//--------------------------------------- +//----------------------------------------------------- int mmo_auth(struct mmo_account* account, int fd) { unsigned int i; @@ -1138,14 +1134,14 @@ int mmo_auth(struct mmo_account* account, int fd) char tmpstr[256]; int len; int newaccount = 0; - char user_password[256]; + char user_password[32+1]; // reserve for md5-ed pw char ip[16]; uint8* sin_addr = (uint8*)&session[fd]->client_addr; sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]); // DNS Blacklist check - if(use_dnsbl) + if( use_dnsbl ) { char r_ip[16]; char ip_dnsbl[256]; @@ -1154,31 +1150,34 @@ int mmo_auth(struct mmo_account* account, int fd) sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); - for (dnsbl_serv = strtok(dnsbl_servs,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",")) + for( dnsbl_serv = strtok(dnsbl_servs,","); !matched && dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",") ) { - if (!matched) { - sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); - if(host2ip(ip_dnsbl)) - matched = true; - } + sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); + if( host2ip(ip_dnsbl) ) + matched = true; } - if (matched) { + if( matched ) + { ShowInfo("DNSBL: (%s) Blacklisted. User Kicked.\n", r_ip); return 3; } } + //Client Version check + if( check_client_version && account->version != 0 && + account->version != client_version_to_connect ) + return 5; - len = strlen(account->userid) - 2; + len = strnlen(account->userid, NAME_LENGTH); // Account creation with _M/_F - if (new_account_flag) + if( new_account_flag ) { - if (account->passwdenc == 0 && account->userid[len] == '_' && - (account->userid[len+1] == 'F' || account->userid[len+1] == 'M' || - account->userid[len+1] == 'f' || account->userid[len+1] == 'm') && - account_id_count <= END_ACCOUNT_NUM && len >= 4 && strlen(account->passwd) >= 4) + if( len > 2 && strnlen(account->passwd, NAME_LENGTH) >= 4 && // valid user and password lengths + account->passwdenc == 0 && // unencoded password + account->userid[len-2] == '_' && memchr("FfMm", (unsigned char)account->userid[len-1], 4) && // _M/_F suffix + account_id_count <= END_ACCOUNT_NUM ) { //only continue if amount in this time limit is allowed (account registration flood protection)[Kevin] if(DIFF_TICK(gettick(), new_reg_tick) < 0 && num_regs >= allowed_regs) { @@ -1187,20 +1186,13 @@ int mmo_auth(struct mmo_account* account, int fd) return 3; } newaccount = 1; - account->userid[len] = '\0'; + account->userid[len-2] = '\0'; } } - //Client Version check - if (check_client_version && account->version != 0 && - account->version != client_version_to_connect) - return 5; - // Strict account search - for(i = 0; i < auth_num; i++) { - if (strcmp(account->userid, auth_dat[i].userid) == 0) - break; - } + ARR_FIND(0, auth_num, i, strcmp(account->userid, auth_dat[i].userid) == 0); + // if there is no creation request and strict account search fails, we do a no sensitive case research for index if (!newaccount && i == auth_num) { i = search_account_index(account->userid); @@ -1210,28 +1202,47 @@ int mmo_auth(struct mmo_account* account, int fd) memcpy(account->userid, auth_dat[i].userid, NAME_LENGTH); // for the possible tests/checks afterwards (copy correcte sensitive case). } - if (i != auth_num) { - if (newaccount) { - login_log("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s, ip: %s)\n", - account->userid, account->userid[len+1], auth_dat[i].pass, account->passwd, ip); + if( i != auth_num ) + { + if (newaccount) + { + login_log("Attempt of creation of an already existant account (account: %s_%c, pass: %s, received pass: %s, ip: %s)\n", account->userid, account->userid[len-1], auth_dat[i].pass, account->passwd, ip); return 1; // 1 = Incorrect Password } - if(use_md5_passwds) + if( use_md5_passwds ) MD5_String(account->passwd, user_password); else - memcpy(user_password, account->passwd, NAME_LENGTH); + safestrncpy(user_password, account->passwd, NAME_LENGTH); - if (!check_password(session[fd]->session_data, account->passwdenc, user_password, auth_dat[i].pass)) + if( !check_password(session[fd]->session_data, account->passwdenc, user_password, auth_dat[i].pass) ) { - login_log("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", - account->userid, auth_dat[i].pass, (account->passwdenc) ? "[MD5]" : account->passwd, ip); + login_log("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", account->userid, auth_dat[i].pass, (account->passwdenc) ? "[MD5]" : account->passwd, ip); return 1; // 1 = Incorrect Password } - if (auth_dat[i].state) { - login_log("Connection refused (account: %s, pass: %s, state: %d, ip: %s)\n", - account->userid, account->passwd, auth_dat[i].state, ip); + if( auth_dat[i].connect_until_time != 0 && auth_dat[i].connect_until_time < time(NULL) ) + { + login_log("Connection refused (account: %s, pass: %s, expired ID, ip: %s)\n", account->userid, account->passwd, ip); + return 2; // 2 = This ID is expired + } + + if( auth_dat[i].ban_until_time != 0 ) + { // account is banned + strftime(tmpstr, 20, date_format, localtime(&auth_dat[i].ban_until_time)); + tmpstr[19] = '\0'; + if( auth_dat[i].ban_until_time > time(NULL) ) { // always banned + login_log("Connection refused (account: %s, pass: %s, banned until %s, ip: %s)\n", account->userid, account->passwd, tmpstr, ip); + return 6; // 6 = Your are Prohibited to log in until %s + } else { // ban is over + login_log("End of ban (account: %s, pass: %s, previously banned until %s -> not more banned, ip: %s)\n", account->userid, account->passwd, tmpstr, ip); + auth_dat[i].ban_until_time = 0; // reset the ban time + } + } + + if( auth_dat[i].state ) + { + login_log("Connection refused (account: %s, pass: %s, state: %d, ip: %s)\n", account->userid, account->passwd, auth_dat[i].state, ip); switch(auth_dat[i].state) { // packet 0x006a value + 1 case 1: // 0 = Unregistered ID case 2: // 1 = Incorrect Password @@ -1261,55 +1272,38 @@ int mmo_auth(struct mmo_account* account, int fd) } } - if (online_check) { + if( online_check ) + { struct online_login_data* data = idb_get(online_db,auth_dat[i].account_id); - if (data && data->char_server > -1) { + if( data && data->char_server > -1 ) + { //Request char servers to kick this account out. [Skotlex] unsigned char buf[8]; ShowNotice("User [%d] is already online - Rejected.\n",auth_dat[i].account_id); WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = auth_dat[i].account_id; charif_sendallwos(-1, buf, 6); - if (data->waiting_disconnect == -1) + if( data->waiting_disconnect == -1 ) data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer, auth_dat[i].account_id, 0); return 3; // Rejected } } - - if (auth_dat[i].ban_until_time != 0) { // if account is banned - strftime(tmpstr, 20, date_format, localtime(&auth_dat[i].ban_until_time)); - tmpstr[19] = '\0'; - if (auth_dat[i].ban_until_time > time(NULL)) { // always banned - login_log("Connection refused (account: %s, pass: %s, banned until %s, ip: %s)\n", - account->userid, account->passwd, tmpstr, ip); - return 6; // 6 = Your are Prohibited to log in until %s - } else { // ban is finished - login_log("End of ban (account: %s, pass: %s, previously banned until %s -> not more banned, ip: %s)\n", - account->userid, account->passwd, tmpstr, ip); - auth_dat[i].ban_until_time = 0; // reset the ban time - } - } - - if (auth_dat[i].connect_until_time != 0 && auth_dat[i].connect_until_time < time(NULL)) { - login_log("Connection refused (account: %s, pass: %s, expired ID, ip: %s)\n", - account->userid, account->passwd, ip); - return 2; // 2 = This ID is expired - } - - login_log("Authentification accepted (account: %s (id: %d), ip: %s)\n", account->userid, auth_dat[i].account_id, ip); - } else { - if (!newaccount) { - login_log("Unknown account (account: %s, received pass: %s, ip: %s)\n", - account->userid, account->passwd, ip); + } + else + { + if( !newaccount ) + { + login_log("Unknown account (account: %s, received pass: %s, ip: %s)\n", account->userid, account->passwd, ip); return 0; // 0 = Unregistered ID - } else { - int new_id = mmo_auth_new(account, account->userid[len+1], "a@a.com"); + } + else + { + int new_id = mmo_auth_new(account, account->userid[len-1], "a@a.com"); unsigned int tick = gettick(); - login_log("Account creation and authentification accepted (account %s (id: %d), pass: %s, sex: %c, connection with _F/_M, ip: %s)\n", - account->userid, new_id, account->passwd, account->userid[len+1], ip); + login_log("Account creation and authentification accepted (account %s (id: %d), pass: %s, sex: %c, connection with _F/_M, ip: %s)\n", account->userid, new_id, account->passwd, account->userid[len-1], ip); auth_before_save_file = 0; // Creation of an account -> save accounts file immediatly - if(DIFF_TICK(tick, new_reg_tick) > 0) + if( DIFF_TICK(tick, new_reg_tick) > 0 ) { //Update the registration check. num_regs = 0; new_reg_tick=tick +time_allowed*1000; @@ -1318,6 +1312,8 @@ int mmo_auth(struct mmo_account* account, int fd) } } + login_log("Authentification accepted (account: %s (id: %d), ip: %s)\n", account->userid, auth_dat[i].account_id, ip); + // auth start : time seed // Platform/Compiler dependant clock() for time check is removed. [Lance] // clock() is originally used to track processing ticks on program execution. @@ -1327,13 +1323,14 @@ int mmo_auth(struct mmo_account* account, int fd) account->account_id = auth_dat[i].account_id; account->login_id1 = rand(); account->login_id2 = rand(); - memcpy(account->lastlogin, auth_dat[i].lastlogin, 24); - memcpy(auth_dat[i].lastlogin, tmpstr, 24); + safestrncpy(account->lastlogin, auth_dat[i].lastlogin, 24); account->sex = auth_dat[i].sex; - if (account->sex != 2 && account->account_id < START_ACCOUNT_NUM) + + if( account->sex != 2 && account->account_id < START_ACCOUNT_NUM ) ShowWarning("Account %s has account id %d! Account IDs must be over %d to work properly!\n", account->userid, account->account_id, START_ACCOUNT_NUM); - strncpy(auth_dat[i].last_ip, ip, 16); + safestrncpy(auth_dat[i].lastlogin, tmpstr, sizeof(auth_dat[i].lastlogin)); + safestrncpy(auth_dat[i].last_ip, ip, sizeof(auth_dat[i].last_ip)); auth_dat[i].logincount++; // Save until for change ip/time of auth is not very useful => limited save for that @@ -2952,14 +2949,8 @@ int parse_admin(int fd) int lan_subnetcheck(uint32 ip) { int i; - - for(i = 0; i < subnet_count; i++) { - if(subnet[i].subnet == (ip & subnet[i].mask)) { - return subnet[i].char_ip; - } - } - - return 0; + ARR_FIND( 0, subnet_count, i, subnet[i].subnet == (ip & subnet[i].mask) ); + return ( i < subnet_count ) ? subnet[i].char_ip : 0; } //---------------------------------------------------------------------------------------- @@ -3175,61 +3166,56 @@ int parse_login(int fd) case 0x2710: // Connection request of a char-server if (RFIFOREST(fd) < 86) return 0; + { + char* server_name; + uint32 server_ip; + uint16 server_port; + + memset(&account, 0, sizeof(account)); + safestrncpy(account.userid, RFIFOP(fd,2), NAME_LENGTH); remove_control_chars(account.userid); + safestrncpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH); remove_control_chars(account.passwd); + account.passwdenc = 0; + server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars(server_name); + server_ip = ntohl(RFIFOL(fd, 54)); + server_port = ntohs(RFIFOW(fd, 58)); + + 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, account.userid, account.passwd, ip); + login_log("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, account.userid, account.passwd, ip); + + result = mmo_auth(&account, fd); + if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 ) { - char* server_name; - uint32 server_ip; - uint16 server_port; - - memset(&account, 0, sizeof(account)); - memcpy(account.userid, RFIFOP(fd,2), NAME_LENGTH); account.userid[23] = '\0'; remove_control_chars(account.userid); - memcpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH); account.passwd[23] = '\0'; remove_control_chars(account.passwd); - account.passwdenc = 0; - server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; remove_control_chars(server_name); - server_ip = ntohl(RFIFOL(fd, 54)); - server_port = ntohs(RFIFOW(fd, 58)); - login_log("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n", - server_name, CONVIP(server_ip), server_port, ip); - - result = mmo_auth(&account, fd); - if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) { - login_log("Connection of the char-server '%s' accepted (account: %s, pass: %s, ip: %s)\n", - server_name, account.userid, account.passwd, ip); - ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); - memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); - server[account.account_id].ip = ntohl(RFIFOL(fd,54)); - server[account.account_id].port = ntohs(RFIFOW(fd,58)); - memcpy(server[account.account_id].name, server_name, 20); - server[account.account_id].users = 0; - server[account.account_id].maintenance = RFIFOW(fd,82); - server[account.account_id].new_ = RFIFOW(fd,84); - server_fd[account.account_id] = fd; - - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2711; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - - session[fd]->func_parse = parse_fromchar; - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - - send_GM_accounts(fd); // send GM account to char-server - } else { - if (server_fd[account.account_id] != -1) { - ShowNotice("Connection of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)\n", - server_name, account.account_id, account.userid, account.passwd, ip); - login_log("Connexion of the char-server '%s' REFUSED - already connected (account: %ld-%s, pass: %s, ip: %s)\n", - server_name, account.account_id, account.userid, account.passwd, ip); - } else { - ShowNotice("Connection of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s).\n", server_name, account.userid, account.passwd, ip); - login_log("Connexion of the char-server '%s' REFUSED (account: %s, pass: %s, ip: %s)\n", - server_name, account.userid, account.passwd, ip); - } - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2711; - WFIFOB(fd,2) = 3; - WFIFOSET(fd,3); - } + ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); + login_log("Connection of the char-server '%s' accepted.\n", server_name); + memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); + server[account.account_id].ip = ntohl(RFIFOL(fd,54)); + server[account.account_id].port = ntohs(RFIFOW(fd,58)); + safestrncpy(server[account.account_id].name, server_name, sizeof(server[account.account_id].name)); + server[account.account_id].users = 0; + server[account.account_id].maintenance = RFIFOW(fd,82); + server[account.account_id].new_ = RFIFOW(fd,84); + server_fd[account.account_id] = fd; + + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2711; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + + session[fd]->func_parse = parse_fromchar; + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + + send_GM_accounts(fd); // send GM account to char-server + } + else + { + ShowNotice("Connection of the char-server '%s' REFUSED.\n", server_name); + login_log("Connection of the char-server '%s' REFUSED.\n", server_name); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2711; + WFIFOB(fd,2) = 3; + WFIFOSET(fd,3); } + } RFIFOSKIP(fd,86); return 0; @@ -3362,7 +3348,7 @@ int parse_login(int fd) //----------------------- // Console Command Parser [Wizputer] //----------------------- -int parse_console(char*buf) +int parse_console(char* buf) { char command[256]; @@ -3377,13 +3363,15 @@ int parse_console(char*buf) strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 ) runflag = 0; - else if( strcmpi("alive", command) == 0 || - strcmpi("status", command) == 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 ){ + else + if( strcmpi("help", command) == 0 ) { printf(CL_BOLD"Help of commands:"CL_RESET"\n"); printf(" To shutdown the server:\n"); - printf(" 'shutdown|exit|qui|end'\n"); + printf(" 'shutdown|exit|quit|end'\n"); printf(" To know if server is alive:\n"); printf(" 'alive|status'\n"); } diff --git a/src/login_sql/Makefile b/src/login_sql/Makefile deleted file mode 100644 index d87a465ea..000000000 --- a/src/login_sql/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -all sql: login-server_sql - -COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ - ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ - ../common/obj/strlib.o ../common/obj/grfio.o \ - ../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/md5calc.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/md5calc.h - -login-server_sql: login.o $(COMMON_OBJ) - $(CC) -o ../../$@ $^ $(LIB_S) - -clean: - rm -f *.o ../../login-server_sql GNUmakefile - -# DO NOT DELETE - -login.o: login.c login.h $(COMMON_H) diff --git a/src/login_sql/Makefile.in b/src/login_sql/Makefile.in new file mode 100644 index 000000000..d10b49b5f --- /dev/null +++ b/src/login_sql/Makefile.in @@ -0,0 +1,46 @@ +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ + ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ + ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o \ + ../common/obj/strlib.o ../common/obj/grfio.o ../common/obj/mapindex.o \ + ../common/obj/ers.o ../common/obj/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 + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + LOGIN_SERVER_SQL_DEPENDS=login.o $(COMMON_OBJ) +else + LOGIN_SERVER_SQL_DEPENDS=needs_mysql +endif + +##################################################################### +.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.o $(COMMON_OBJ) @LIBS@ @MYSQL_LIBS@ + +clean: + rm -f *.o ../../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 + +# DO NOT DELETE + +login.o: login.c login.h $(COMMON_H) + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< diff --git a/src/login_sql/login.c b/src/login_sql/login.c index 9411c6fec..bc3c1117a 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -12,20 +12,13 @@ #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 <sys/stat.h> // for stat/lstat/fstat -#include <signal.h> -#include <fcntl.h> #include <string.h> - -//add include for DBMS(mysql) -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <mysql.h> +#include <sys/stat.h> // for stat/lstat/fstat struct Login_Config { @@ -59,7 +52,7 @@ int server_fd[MAX_SERVERS]; // char server sockets struct mmo_char_server server[MAX_SERVERS]; // char server data // Advanced subnet check [LuzZza] -struct _subnet { +struct s_subnet { uint32 subnet; uint32 mask; uint32 char_ip; @@ -78,13 +71,10 @@ int time_allowed = 10; //in seconds int num_regs = 0; unsigned int new_reg_tick = 0; -MYSQL mysql_handle; -MYSQL_RES* sql_res ; -MYSQL_ROW sql_row ; -char tmpsql[65535]; +Sql* sql_handle; // database parameters -int login_server_port = 3306; +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"; @@ -127,19 +117,19 @@ struct online_login_data { //----------------------------------------------------- -struct dbt *online_db; +struct dbt* online_db; static void* create_online_user(DBKey key, va_list args) { - struct online_login_data *p; - p = aCalloc(1, sizeof(struct online_login_data)); + 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; + return p; } -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len); +int charif_sendallwos(int sfd, uint8* buf, size_t len); static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data); //----------------------------------------------------- @@ -148,12 +138,12 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data void add_online_user(int char_server, int account_id) { - struct online_login_data *p; - if (!login_config.online_check) + struct online_login_data* p; + if( !login_config.online_check ) return; p = idb_ensure(online_db, account_id, create_online_user); p->char_server = char_server; - if (p->waiting_disconnect != -1) + if( p->waiting_disconnect != -1 ) { delete_timer(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = -1; @@ -162,19 +152,20 @@ void add_online_user(int char_server, int account_id) void remove_online_user(int account_id) { - if(!login_config.online_check) + if( !login_config.online_check ) return; - if (account_id == 99) { // reset all to offline + if( account_id == 99 ) + {// reset all to offline online_db->clear(online_db, NULL); // purge db return; } - idb_remove(online_db,account_id); + idb_remove(online_db, account_id); } static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data) { - struct online_login_data *p; - if ((p= idb_get(online_db, id)) != NULL && p->waiting_disconnect == id) + struct online_login_data* p = idb_get(online_db, id); + if( p != NULL && p->waiting_disconnect == id ) { p->waiting_disconnect = -1; remove_online_user(id); @@ -184,7 +175,7 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, int data static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) { - unsigned char buf[2]; + uint8 buf[2]; ShowInfo("IP Sync in progress...\n"); WBUFW(buf,0) = 0x2735; charif_sendallwos(-1, buf, 2); @@ -196,32 +187,30 @@ static int sync_ip_addresses(int tid, unsigned int tick, int id, int data) //----------------------------------------------------- void read_gm_account(void) { - if(!login_config.login_gm_read) - return; - sprintf(tmpsql, "SELECT `%s`,`%s` FROM `%s` WHERE `%s`> '0'",login_db_account_id,login_db_level,login_db,login_db_level); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return; //Failed to read GM list! - } + if( !login_config.login_gm_read ) + return;// char server's job - if (gm_account_db != NULL) + 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) ) { - aFree(gm_account_db); - gm_account_db = NULL; + Sql_ShowDebug(sql_handle); + return;// Failed to read GM list! } - GM_num = 0; - - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - gm_account_db = (struct gm_account*)aCalloc((size_t)mysql_num_rows(sql_res), sizeof(struct gm_account)); - while ((sql_row = mysql_fetch_row(sql_res))) { - gm_account_db[GM_num].account_id = atoi(sql_row[0]); - gm_account_db[GM_num].level = atoi(sql_row[1]); - GM_num++; - } - mysql_free_result(sql_res); + + 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); } //----------------------------------------------------- @@ -233,27 +222,32 @@ void send_GM_accounts(int fd) uint8 buf[32767]; uint16 len; - if(!login_config.login_gm_read) + if( !login_config.login_gm_read ) return; len = 4; WBUFW(buf,0) = 0x2732; - for(i = 0; i < GM_num; i++) + 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) { + 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) { + 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 + if( fd == -1 )// send to all charservers charif_sendallwos(-1, buf, len); - else { // send only to target + else + {// send only to target WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); @@ -268,27 +262,20 @@ void send_GM_accounts(int fd) int login_sql_ping(int tid, unsigned int tick, int id, int data) { ShowInfo("Pinging SQL server to keep connection alive...\n"); - mysql_ping(&mysql_handle); + Sql_Ping(sql_handle); return 0; } int sql_ping_init(void) { - int connection_timeout, connection_ping_interval; + 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 (!mysql_query(&mysql_handle, "SHOW VARIABLES LIKE 'wait_timeout'") - && (sql_res = mysql_store_result(&mysql_handle)) != NULL) { - sql_row = mysql_fetch_row(sql_res); - if (sql_row) - connection_timeout = atoi(sql_row[1]); - if (connection_timeout < 60) - connection_timeout = 60; - mysql_free_result(sql_res); - } + 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 @@ -305,34 +292,26 @@ int mmo_auth_sqldb_init(void) { ShowStatus("Login server init....\n"); - mysql_init(&mysql_handle); + sql_handle = Sql_Malloc(); // DB connection start ShowStatus("Connect Login Database Server....\n"); - if (!mysql_real_connect(&mysql_handle, login_server_ip, login_server_id, login_server_pw, login_server_db, login_server_port, (char *)NULL, 0)) { - ShowFatalError("%s\n", mysql_error(&mysql_handle)); + 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(1); - } else { - ShowStatus("Connect success!\n"); } - if( strlen(default_codepage) > 0 ) { - sprintf( tmpsql, "SET NAMES %s", default_codepage ); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + else + { + ShowStatus("Connect success!\n"); } - if (login_config.log_login) - { - sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100','login server started')", loginlog_db); + if( default_codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) ) + Sql_ShowDebug(sql_handle); - //query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + 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(); @@ -348,32 +327,23 @@ void mmo_db_close(void) int i, fd; //set log. - if (login_config.log_login) - { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '0', 'lserver','100', 'login server shutdown')", loginlog_db); - - //query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + 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++) { - if ((fd = server_fd[i]) >= 0) - { //Clean only data related to servers we are connected to. [Skotlex] - sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index` = '%d'", i); - if (mysql_query(&mysql_handle, tmpsql)) - { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + for( i = 0; i < MAX_SERVERS; ++i ) + { + fd = server_fd[i]; + 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); } } - mysql_close(&mysql_handle); + Sql_Free(sql_handle); + sql_handle = NULL; ShowStatus("close DB connect....\n"); - if (login_fd > 0) + if( login_fd > 0 ) do_close(login_fd); } @@ -383,75 +353,66 @@ void mmo_db_close(void) int mmo_auth_new(struct mmo_account* account, char sex) { unsigned int tick = gettick(); - char user_password[256]; + char md5buf[32+1]; + SqlStmt* stmt; + //Account Registration Flood Protection by [Kevin] - if(DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs) { + if( DIFF_TICK(tick, new_reg_tick) < 0 && num_regs >= allowed_regs ) + { ShowNotice("Account registration denied (registration limit exceeded)\n"); return 3; } - //Check for preexisting account - sprintf(tmpsql, "SELECT `%s` FROM `%s` WHERE `userid` = '%s'", login_db_userid, login_db, account->userid); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 1; //Return Incorrect user/pass? + // 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_NumRows(stmt) > 0 ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return 1; // incorrect user/pass } - - sql_res = mysql_store_result(&mysql_handle); - if(mysql_num_rows(sql_res) > 0){ - mysql_free_result(sql_res); - return 1; //Already exists, return incorrect user/pass. + SqlStmt_Free(stmt); + + // insert new entry into db + //TODO: error checking + stmt = SqlStmt_Malloc(sql_handle); + SqlStmt_Prepare(stmt, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES (?, ?, '%c', 'a@a.com')", login_db, login_db_userid, login_db_user_pass, TOUPPER(sex)); + SqlStmt_BindParam(stmt, 0, SQLDT_STRING, account->userid, strnlen(account->userid, NAME_LENGTH)); + if( login_config.use_md5_passwds ) + { + MD5_String(account->passwd, md5buf); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, md5buf, 32); } - mysql_free_result(sql_res); //Only needed for the already-exists check... - - mysql_real_escape_string(&mysql_handle, account->userid, account->userid, strlen(account->userid)); - mysql_real_escape_string(&mysql_handle, account->passwd, account->passwd, strlen(account->passwd)); - - sex = TOUPPER(sex); - - if (login_config.use_md5_passwds) - MD5_String(account->passwd, user_password); else - jstrescapecpy(user_password, account->passwd); - - ShowInfo("New account: user: %s with passwd: %s sex: %c\n", account->userid, user_password, sex); - - sprintf(tmpsql, "INSERT INTO `%s` (`%s`, `%s`, `sex`, `email`) VALUES ('%s', '%s', '%c', '%s')", login_db, login_db_userid, login_db_user_pass, account->userid, user_password, sex, "a@a.com"); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, account->passwd, strnlen(account->passwd, NAME_LENGTH)); + SqlStmt_Execute(stmt); + SqlStmt_Free(stmt); - if(mysql_query(&mysql_handle, tmpsql)){ - //Failed to insert new acc :/ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 1; - } + ShowInfo("New account: userid='%s' passwd='%s' sex='%c'\n", account->userid, account->passwd, TOUPPER(sex)); - if(mysql_field_count(&mysql_handle) == 0 && - mysql_insert_id(&mysql_handle) < START_ACCOUNT_NUM) { - //Invalid Account ID! Must update it. - int id = (int)mysql_insert_id(&mysql_handle); - sprintf(tmpsql, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%d'", login_db, login_db_account_id, START_ACCOUNT_NUM, login_db_account_id, id); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowError("New account %s has an invalid account ID [%d] which could not be updated (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM); - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + if( Sql_LastInsertId(sql_handle) < START_ACCOUNT_NUM ) + {// Invalid Account ID! Must update it. + uint64 id = Sql_LastInsertId(sql_handle); + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%lld'", login_db, login_db_account_id, START_ACCOUNT_NUM, login_db_account_id, id) ) + { + Sql_ShowDebug(sql_handle); + ShowError("New account '%s' has an invalid account ID [%lld] which could not be updated (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM); //Just delete it and fail. - sprintf(tmpsql, "DELETE FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, id); - if(mysql_query(&mysql_handle, tmpsql)){ - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `%s`='%lld'", login_db, login_db_account_id, id) ) + Sql_ShowDebug(sql_handle); return 1; } - ShowNotice("Updated New account %s's ID %d->%d (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM, START_ACCOUNT_NUM); + ShowNotice("Updated New account '%s' ID %d->%d (account_id must be %d or higher).", account->userid, id, START_ACCOUNT_NUM, START_ACCOUNT_NUM); } - if(DIFF_TICK(tick, new_reg_tick) > 0) - { //Update the registration check. - num_regs=0; - new_reg_tick=tick+time_allowed*1000; + if( DIFF_TICK(tick, new_reg_tick) > 0 ) + {// Update the registration check. + num_regs = 0; + new_reg_tick = tick + time_allowed*1000; } - num_regs++; - + ++num_regs; return 0; } @@ -459,16 +420,19 @@ int mmo_auth_new(struct mmo_account* account, char sex) //-------------------------------------------------------------------- // Packet send to all char-servers, except one (wos: without our self) //-------------------------------------------------------------------- -int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) +int charif_sendallwos(int sfd, uint8* buf, size_t len) { - int i, c, fd; + int i, c; - for(i = 0, c = 0; i < MAX_SERVERS; i++) { - if ((fd = server_fd[i]) > 0 && fd != sfd) { + for( i = 0, c = 0; i < MAX_SERVERS; ++i ) + { + int fd = server_fd[i]; + if( session_isValid(fd) && fd != sfd ) + { WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); - c++; + ++c; } } @@ -482,7 +446,9 @@ int charif_sendallwos(int sfd, unsigned char *buf, unsigned int len) 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'; + + snprintf(md5str, sizeof(md5str), "%s%s", str1, str2); + md5str[sizeof(md5str)-1] = '\0'; MD5_String2binary(md5str, md5bin); return (0==memcmp(passwd, md5bin, 16)); @@ -512,134 +478,144 @@ bool check_password(struct login_session_data* ld, int passwdenc, const char* pa int mmo_auth(struct mmo_account* account, int fd) { time_t ban_until_time; - char t_uid[256]; + char esc_userid[NAME_LENGTH*2+1];// escaped username char user_password[256], password[256]; long connect_until; int state; + size_t len; + char* data; char ip[16]; - uint32 ipl = session[fd]->client_addr; - uint8* sin_addr = (uint8*)&ipl; - sprintf(ip, "%d.%d.%d.%d", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]); + uint8* sin_addr = (uint8*)&session[fd]->client_addr; + sprintf(ip, "%u.%u.%u.%u", sin_addr[3], sin_addr[2], sin_addr[1], sin_addr[0]); // DNS Blacklist check - if(login_config.use_dnsbl) + if( login_config.use_dnsbl ) { char r_ip[16]; char ip_dnsbl[256]; char *dnsbl_serv; bool matched = false; - sprintf(r_ip, "%d.%d.%d.%d", sin_addr[0], sin_addr[1], sin_addr[2], sin_addr[3]); + 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,","); dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",")) + for( dnsbl_serv = strtok(login_config.dnsbl_servs,","); !matched && dnsbl_serv != NULL; dnsbl_serv = strtok(NULL,",") ) { - if (!matched) { - sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); - if(host2ip(ip_dnsbl)) - matched = true; - } + sprintf(ip_dnsbl, "%s.%s", r_ip, dnsbl_serv); + if( host2ip(ip_dnsbl) ) + matched = true; } - if (matched) { + if( matched ) + { ShowInfo("DNSBL: (%s) Blacklisted. User Kicked.\n", r_ip); return 3; } } + //Client Version check + if( login_config.check_client_version && account->version != 0 && + account->version != login_config.client_version_to_connect ) + return 5; + + len = strnlen(account->userid, NAME_LENGTH); + // Account creation with _M/_F - if (login_config.new_account_flag) + if( login_config.new_account_flag ) { - int len = strlen(account->userid) - 2; - if (account->passwdenc == 0 && account->userid[len] == '_' && - (account->userid[len+1] == 'F' || account->userid[len+1] == 'M' || - account->userid[len+1] == 'f' || account->userid[len+1] == 'm') && - len >= 4 && strlen(account->passwd) >= 4) + if( len > 2 && strnlen(account->passwd, NAME_LENGTH) >= 4 && // valid user and password lengths + account->passwdenc == 0 &&// unencoded password + account->userid[len-2] == '_' && memchr("FfMm", (unsigned char)account->userid[len-1], 4) ) // _M/_F suffix { int result; - account->userid[len] = '\0'; //Terminating the name. - if ((result = mmo_auth_new(account, account->userid[len+1]))) - return result; //Failed to make account. [Skotlex]. + account->userid[len-2] = '\0';// terminate the name. + result = mmo_auth_new(account, account->userid[len-1]); + if( result ) + return result;// Failed to make account. [Skotlex]. } } - jstrescapecpy(t_uid,account->userid); + // escape username + Sql_EscapeStringLen(sql_handle, esc_userid, account->userid, len); // retrieve login entry for the specified username - sprintf(tmpsql, "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" : "", t_uid); + 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); //login {0-account_id/1-user_pass/2-lastlogin/3-sex/4-connect_untl/5-ban_until/6-state/7-level} - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (!sql_res) { - ShowError("mmo_auth DB result error ! \n"); - return 0; - } - sql_row = mysql_fetch_row(sql_res); - if (!sql_row) { - //there's no id. - ShowNotice("auth failed: no such account %s\n", account->userid); - mysql_free_result(sql_res); + 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; } - account->account_id = atoi(sql_row[0]); - strncpy(password, sql_row[1], sizeof(password)-1); - strncpy(account->lastlogin, sql_row[2], 24); - account->sex = sql_row[3][0] == 'S' ? 2 : sql_row[3][0]=='M' ? 1 : 0; - connect_until = atol(sql_row[4]); - ban_until_time = atol(sql_row[5]); - state = atoi(sql_row[6]); - account->level = atoi(sql_row[7]); - if (account->level > 99) account->level = 99; - - //This function has too many leaks because this is only free'd on the end. - //Better avoid that and free it as soon as possible. [Skotlex] - mysql_free_result(sql_res); + Sql_NextRow(sql_handle); //TODO: error checking? - //Client Version check - if(login_config.check_client_version && account->version != 0 && - account->version != login_config.client_version_to_connect) - return 5; + Sql_GetData(sql_handle, 0, &data, &len); + account->account_id = atoi(data); - switch (state) { - case -3: //id is banned - case -2: //dynamic ban - return state; + Sql_GetData(sql_handle, 1, &data, &len); + if( len > sizeof(password) - 1 ) + { +#if defined(DEBUG) + ShowDebug("mmo_auth: password buffer is too small (len=%u,buflen=%u)\n", len, sizeof(password)); +#endif + len = sizeof(password) - 1; } + memcpy(password, data, len); + password[len] = '\0'; + + Sql_GetData(sql_handle, 2, &data, &len); safestrncpy(account->lastlogin, data, sizeof(account->lastlogin)); + Sql_GetData(sql_handle, 3, &data, &len); account->sex = (*data == 'S' ? 2 : *data == 'M' ? 1 : 0); + Sql_GetData(sql_handle, 4, &data, &len); connect_until = atol(data); + Sql_GetData(sql_handle, 5, &data, &len); ban_until_time = atol(data); + Sql_GetData(sql_handle, 6, &data, &len); state = atoi(data); + Sql_GetData(sql_handle, 7, &data, &len); account->level = atoi(data); + if( account->level > 99 ) + account->level = 99; - if (login_config.use_md5_passwds) + Sql_FreeResult(sql_handle); + + if( login_config.use_md5_passwds ) MD5_String(account->passwd, user_password); else - memcpy(user_password, account->passwd, NAME_LENGTH); + safestrncpy(user_password, account->passwd, NAME_LENGTH); - if (!check_password(session[fd]->session_data, account->passwdenc, user_password, password)) + if( !check_password(session[fd]->session_data, account->passwdenc, user_password, password) ) { - ShowInfo("Invalid password (account: %s, pass: %s, received pass: %s, ip: %s)\n", - account->userid, password, (account->passwdenc) ? "[MD5]" : account->passwd, ip); + ShowInfo("Invalid password (account: '%s', pass: '%s', received pass: '%s', ip: %s)\n", + esc_userid, password, (account->passwdenc) ? "[MD5]" : user_password, ip); return 1; // 1 = Incorrect Password } - if (ban_until_time != 0) { // if account is banned - if (ban_until_time > time(NULL)) // always banned + if( connect_until != 0 && connect_until < time(NULL) ) + return 2; // 2 = This ID is expired + + if( ban_until_time != 0 ) + {// account is banned + if( ban_until_time > time(NULL) )// still banned return 6; // 6 = Your are Prohibited to log in until %s - sprintf(tmpsql, "UPDATE `%s` SET `ban_until`='0' %s WHERE `%s`= '%d'", - login_db, state==7?",state='0'":"", - login_db_account_id, account->account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `ban_until`='0' %s WHERE `%s`= '%d'", + login_db, (state == 7 ? ",state='0'" : ""), login_db_account_id, account->account_id) ) + Sql_ShowDebug(sql_handle); } - if (state) - switch(state) { // packet 0x006a value + 1 + switch( state ) + { + case -3: //id is banned + case -2: //dynamic ban + return state; + } + + switch( state ) + {// packet 0x006a value + 1 + case 0: + break; case 1: // 0 = Unregistered ID case 2: // 1 = Incorrect Password case 3: // 2 = This ID is expired @@ -668,19 +644,18 @@ int mmo_auth(struct mmo_account* account, int fd) return 99; // 99 = ID has been totally erased } - if (connect_until != 0 && connect_until < time(NULL)) - return 2; // 2 = This ID is expired - - if (login_config.online_check) { - struct online_login_data* data = idb_get(online_db,account->account_id); - if (data && data->char_server > -1) { + if( login_config.online_check ) + { + struct online_login_data* data = idb_get(online_db, account->account_id); + if( data && data->char_server > -1 ) + { //Request char servers to kick this account out. [Skotlex] - unsigned char buf[8]; - ShowNotice("User [%s] is already online - Rejected.\n",account->userid); + uint8 buf[8]; + ShowNotice("User '%s' is already online - Rejected.\n", account->userid); WBUFW(buf,0) = 0x2734; WBUFL(buf,2) = account->account_id; charif_sendallwos(-1, buf, 6); - if (data->waiting_disconnect == -1) + if( data->waiting_disconnect == -1 ) data->waiting_disconnect = add_timer(gettick()+30000, waiting_disconnect_timer, account->account_id, 0); return 3; // Rejected } @@ -689,30 +664,30 @@ int mmo_auth(struct mmo_account* account, int fd) account->login_id1 = rand(); account->login_id2 = rand(); - if (account->sex != 2 && account->account_id < START_ACCOUNT_NUM) + if( account->sex != 2 && account->account_id < START_ACCOUNT_NUM ) ShowWarning("Account %s has account id %d! Account IDs must be over %d to work properly!\n", account->userid, account->account_id, START_ACCOUNT_NUM); - sprintf(tmpsql, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount` +1, `last_ip`='%s' WHERE `%s` = '%d'", - login_db, ip, login_db_account_id, account->account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - return -1; + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `lastlogin` = NOW(), `logincount`=`logincount`+1, `last_ip`='%s' WHERE `%s` = '%d'", + login_db, ip, login_db_account_id, account->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; + struct online_login_data* p = (struct online_login_data*)data; int server = va_arg(ap, int); - if (server == -1) { + if( server == -1 ) + { p->char_server = -1; - if (p->waiting_disconnect != -1) + if( p->waiting_disconnect != -1 ) { delete_timer(p->waiting_disconnect, waiting_disconnect_timer); p->waiting_disconnect = -1; } - } else if (p->char_server == server) + } + else if( p->char_server == server ) p->char_server = -2; //Char server disconnected. return 0; } @@ -728,44 +703,40 @@ int parse_fromchar(int fd) char ip[16]; ip2str(ipl, ip); - for(id = 0; id < MAX_SERVERS; id++) - if (server_fd[id] == fd) + for( id = 0; id < MAX_SERVERS; ++id ) + if( server_fd[id] == fd ) break; - if (id == MAX_SERVERS) { // not a char server + if( id == MAX_SERVERS ) + {// not a char server set_eof(fd); do_close(fd); return 0; } - if(session[fd]->eof) { + if( session[fd]->eof ) + { ShowStatus("Char-server '%s' has disconnected.\n", server[id].name); server_fd[id] = -1; memset(&server[id], 0, sizeof(struct mmo_char_server)); - online_db->foreach(online_db,online_db_setoffline,id); //Set all chars from this char server to offline. - sprintf(tmpsql, "DELETE FROM `sstatus` WHERE `index`='%d'", id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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); do_close(fd); return 0; } - while (RFIFOREST(fd) >= 2) + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch (command) + switch( command ) { case 0x2709: // request from map-server via char-server to reload GM accounts - if (login_config.log_login) + if( login_config.log_login ) { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`log`) VALUES (NOW(), '%u', '%s', 'GM reload request')", loginlog_db, ipl, server[id].name); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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 @@ -774,12 +745,13 @@ int parse_fromchar(int fd) break; case 0x2712: // request from char-server to authenticate an account - if (RFIFOREST(fd) < 19) + if( RFIFOREST(fd) < 19 ) return 0; { int account_id; account_id = RFIFOL(fd,2); // speed up - for(i = 0; i < AUTH_FIFO_SIZE; i++) { + for( i = 0; i < AUTH_FIFO_SIZE; ++i ) + { if( auth_fifo[i].account_id == account_id && auth_fifo[i].login_id1 == RFIFOL(fd,6) && auth_fifo[i].login_id2 == RFIFOL(fd,10) && @@ -792,30 +764,45 @@ int parse_fromchar(int fd) } } - if (i != AUTH_FIFO_SIZE && account_id > 0) { // send ack - time_t connect_until_time = 0; - char email[40] = ""; - account_id=RFIFOL(fd,2); - sprintf(tmpsql, "SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'", login_db, login_db_account_id, account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); - connect_until_time = atol(sql_row[1]); - strncpy(email, sql_row[0], 40); email[39] = 0; - mysql_free_result(sql_res); + if( i != AUTH_FIFO_SIZE && account_id > 0 ) + {// send ack + uint32 connect_until_time = 0; + char email[40]; + + memset(email, 0, sizeof(email)); + account_id = RFIFOL(fd,2); + 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); + if( len > sizeof(email) ) + { +#if defined(DEBUG) + ShowDebug("parse_fromchar:0x2712: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email)); +#endif + len = sizeof(email); + } + memcpy(email, data, len); + + Sql_GetData(sql_handle, 1, &data, NULL); + connect_until_time = (uint32)strtoul(data, NULL, 10); + + Sql_FreeResult(sql_handle); } WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; WFIFOB(fd,6) = 0; memcpy(WFIFOP(fd, 7), email, 40); - WFIFOL(fd,47) = (unsigned long) connect_until_time; + WFIFOL(fd,47) = connect_until_time; WFIFOSET(fd,51); - } else { + } + else + { WFIFOHEAD(fd,51); WFIFOW(fd,0) = 0x2713; WFIFOL(fd,2) = account_id; @@ -832,17 +819,13 @@ int parse_fromchar(int fd) return 0; // how many users on world? (update) - if (server[id].users != RFIFOL(fd,2)) + if( server[id].users != RFIFOL(fd,2) ) { ShowStatus("set users %s : %d\n", server[id].name, RFIFOL(fd,2)); server[id].users = RFIFOL(fd,2); - sprintf(tmpsql,"UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `sstatus` SET `user` = '%d' WHERE `index` = '%d'", server[id].users, id) ) + Sql_ShowDebug(sql_handle); } // send some answer WFIFOHEAD(fd,6); @@ -853,31 +836,44 @@ int parse_fromchar(int fd) 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) + if( RFIFOREST(fd) < 6 ) return 0; { int account_id; - time_t connect_until_time = 0; - char email[40] = ""; + uint32 connect_until_time = 0; + char email[40]; + + memset(email, 0, sizeof(email)); account_id = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `email`,`connect_until` FROM `%s` WHERE `%s`='%d'",login_db, login_db_account_id, account_id); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); - connect_until_time = atol(sql_row[1]); - strcpy(email, sql_row[0]); + + 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); + if( len > sizeof(email) ) + { +#if defined(DEBUG) + ShowDebug("parse_fromchar:0x2716: email is too long (len=%u,maxlen=%u)\n", len, sizeof(email)); +#endif + len = sizeof(email); + } + memcpy(email, data, len); + + Sql_GetData(sql_handle, 1, &data, NULL); + connect_until_time = (uint32)strtoul(data, NULL, 10); + + Sql_FreeResult(sql_handle); } - mysql_free_result(sql_res); //printf("parse_fromchar: E-mail/limited time request from '%s' server (concerned account: %d)\n", server[id].name, RFIFOL(fd,2)); WFIFOHEAD(fd,50); WFIFOW(fd,0) = 0x2717; WFIFOL(fd,2) = RFIFOL(fd,2); memcpy(WFIFOP(fd, 6), email, 40); - WFIFOL(fd,46) = (unsigned long) connect_until_time; + WFIFOL(fd,46) = connect_until_time; WFIFOSET(fd,50); RFIFOSKIP(fd,6); @@ -905,43 +901,58 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 86) return 0; { - int acc; + int account_id; char actual_email[40], new_email[40]; - acc = RFIFOL(fd,2); + + account_id = RFIFOL(fd,2); memcpy(actual_email, RFIFOP(fd,6), 40); memcpy(new_email, RFIFOP(fd,46), 40); - if (e_mail_check(actual_email) == 0) + if( e_mail_check(actual_email) == 0 ) ShowWarning("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, acc, ip); - else if (e_mail_check(new_email) == 0) + server[id].name, account_id, ip); + else if( e_mail_check(new_email) == 0 ) ShowWarning("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, acc, ip); - else if (strcmpi(new_email, "a@a.com") == 0) + server[id].name, account_id, ip); + else if( strcmpi(new_email, "a@a.com") == 0 ) ShowWarning("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, acc, ip); - else { - sprintf(tmpsql, "SELECT `%s`,`email` FROM `%s` WHERE `%s` = '%d'", login_db_userid, login_db, login_db_account_id, acc); - if (mysql_query(&mysql_handle, tmpsql)) + 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( len > sizeof(actual_email) ) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); +#if defined(DEBUG) + ShowDebug("parse_fromchar:0x2722: email is too long (len=%u,maxlen=%u)\n", len, sizeof(actual_email)); +#endif + len = sizeof(actual_email); } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); //row fetching - - if (strcmpi(sql_row[1], actual_email) == 0) { - sprintf(tmpsql, "UPDATE `%s` SET `email` = '%s' WHERE `%s` = '%d'", login_db, new_email, login_db_account_id, acc); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - 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, acc, sql_row[0], actual_email, ip); + 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); + if( len > NAME_LENGTH ) + { +#if defined(DEBUG) + ShowDebug("parse_fromchar:0x2722: userid is too long (len=%u,maxlen=%u)\n", len, NAME_LENGTH); +#endif + len = NAME_LENGTH; } - } + 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); } RFIFOSKIP(fd, 86); @@ -952,33 +963,31 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 10) return 0; { - int acc, statut; - acc = RFIFOL(fd,2); - statut = RFIFOL(fd,6); - sprintf(tmpsql, "SELECT `state` FROM `%s` WHERE `%s` = '%d'", login_db, login_db_account_id, acc); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); // row fetching - } - if (atoi(sql_row[0]) != statut && statut != 0) { - unsigned char buf[16]; - WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; - 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); - } - sprintf(tmpsql,"UPDATE `%s` SET `state` = '%d' WHERE `%s` = '%d'", login_db, statut,login_db_account_id,acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + int account_id, state; + account_id = RFIFOL(fd,2); + state = RFIFOL(fd,6); + 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); + RFIFOSKIP(fd,10); } break; @@ -987,51 +996,49 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 18) return 0; { - int acc; + int account_id; struct tm *tmtime; - time_t timestamp, tmptime; - acc = RFIFOL(fd,2); - sprintf(tmpsql, "SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle); - if (sql_res) { - sql_row = mysql_fetch_row(sql_res); // row fetching + time_t tmptime = 0; + time_t timestamp = time(NULL); + + account_id = RFIFOL(fd,2); + 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; } - tmptime = atol(sql_row[0]); - if (tmptime == 0 || tmptime < time(NULL)) - timestamp = time(NULL); - else - timestamp = tmptime; tmtime = localtime(×tamp); - tmtime->tm_year = tmtime->tm_year + (short)RFIFOW(fd,6); - tmtime->tm_mon = tmtime->tm_mon + (short)RFIFOW(fd,8); - tmtime->tm_mday = tmtime->tm_mday + (short)RFIFOW(fd,10); - tmtime->tm_hour = tmtime->tm_hour + (short)RFIFOW(fd,12); - tmtime->tm_min = tmtime->tm_min + (short)RFIFOW(fd,14); - tmtime->tm_sec = tmtime->tm_sec + (short)RFIFOW(fd,16); + tmtime->tm_year = tmtime->tm_year + (int16)RFIFOW(fd,6); + tmtime->tm_mon = tmtime->tm_mon + (int16)RFIFOW(fd,8); + tmtime->tm_mday = tmtime->tm_mday + (int16)RFIFOW(fd,10); + tmtime->tm_hour = tmtime->tm_hour + (int16)RFIFOW(fd,12); + tmtime->tm_min = tmtime->tm_min + (int16)RFIFOW(fd,14); + tmtime->tm_sec = tmtime->tm_sec + (int16)RFIFOW(fd,16); timestamp = mktime(tmtime); - if (timestamp != -1) { - if (timestamp <= time(NULL)) + if( timestamp != (time_t)-1 ) + { + if( timestamp <= time(NULL) ) timestamp = 0; - if (tmptime != timestamp) { - if (timestamp != 0) { - unsigned char buf[16]; + if( tmptime != timestamp ) + { + if( timestamp != 0 ) + { + uint8 buf[11]; WBUFW(buf,0) = 0x2731; - WBUFL(buf,2) = acc; + WBUFL(buf,2) = account_id; WBUFB(buf,6) = 1; // 0: change of statut, 1: ban - WBUFL(buf,7) = (unsigned int)timestamp; // status or final date of a banishment + WBUFL(buf,7) = (uint32)timestamp; // status or final date of a banishment charif_sendallwos(-1, buf, 11); } - ShowNotice("Account: %d Banned until: %ld\n", acc, timestamp); - sprintf(tmpsql, "UPDATE `%s` SET `ban_until` = '%ld' WHERE `%s` = '%d'", login_db, (unsigned long)timestamp, login_db_account_id, acc); - // query - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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); } } @@ -1043,110 +1050,106 @@ int parse_fromchar(int fd) if (RFIFOREST(fd) < 6) return 0; { - int acc,sex; - unsigned char buf[16]; - acc = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `sex` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - return 0; - } + int account_id; + int sex; + uint8 buf[16]; + + account_id = RFIFOL(fd,2); + 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) ) + { + char* data; - sql_res = mysql_store_result(&mysql_handle) ; + Sql_GetData(sql_handle, 0, &data, NULL); + if( *data == 'M' || *data == 'm' ) + sex = 0; //Change to female + else + sex = 1; //Change to male - if (sql_res) { - if (mysql_num_rows(sql_res) == 0) { - mysql_free_result(sql_res); - return 0; - } - sql_row = mysql_fetch_row(sql_res); //row fetching - } + if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex ? 'M' : 'F'), login_db_account_id, account_id) ) + Sql_ShowDebug(sql_handle); - if (strcmpi(sql_row[0], "M") == 0) - sex = 0; //Change to female - else - sex = 1; //Change to make - sprintf(tmpsql,"UPDATE `%s` SET `sex` = '%c' WHERE `%s` = '%d'", login_db, (sex?'M':'F'), login_db_account_id, acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + WBUFW(buf,0) = 0x2723; + WBUFL(buf,2) = account_id; + WBUFB(buf,6) = sex; + charif_sendallwos(-1, buf, 7); } - WBUFW(buf,0) = 0x2723; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - charif_sendallwos(-1, buf, 7); RFIFOSKIP(fd,6); } break; case 0x2728: // save account_reg2 - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + if( RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2) ) return 0; - if (RFIFOL(fd,4) > 0) { - int acc,p,j,len; - char str[32]; - char temp_str[64]; //Needs twice as much space as the original string. - char temp_str2[512]; - char value[256]; - unsigned char *buf; - acc = RFIFOL(fd,4); - buf = (unsigned char*)aCalloc(RFIFOW(fd,2)+1, sizeof(unsigned char)); + if( RFIFOL(fd,4) > 0 ) + { + SqlStmt* stmt; + int account_id; + size_t off; + + account_id = RFIFOL(fd,4); + //Delete all global account variables.... - sprintf(tmpsql,"DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d';",reg_db,acc); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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.... - for(j=0,p=13;j<ACCOUNT_REG2_NUM && p<RFIFOW(fd,2);j++){ - sscanf(RFIFOP(fd,p), "%31c%n",str,&len); - str[len]='\0'; - p +=len+1; //+1 to skip the '\0' between strings. - sscanf(RFIFOP(fd,p), "%255c%n",value,&len); - value[len]='\0'; - p +=len+1; - - sprintf(tmpsql,"INSERT INTO `%s` (`type`, `account_id`, `str`, `value`) VALUES ( 1 , '%d' , '%s' , '%s');", reg_db, acc, jstrescapecpy(temp_str,str), jstrescapecpy(temp_str2,value)); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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 ) + { + uint8* p; + size_t len; + + // str + p = (uint8*)RFIFOP(fd,off); + len = strlen(p); + SqlStmt_BindParam(stmt, 0, SQLDT_STRING, p, len); + off += len + 1; + + // value + p = (uint8*)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); + + {// Send to char + //uint8* buf; + //CREATE(buf, uint8, RFIFOW(fd,2)); + //memcpy(WBUFP(buf,0), RFIFOP(fd,0), RFIFOW(fd,2)); + //WBUFW(buf,0)=0x2729; + //charif_sendallwos(fd, buf, WBUFW(buf,2)); + //aFree(buf); + + RFIFOW(fd,0) = 0x2729;// reusing read buffer + charif_sendallwos(fd, RFIFOP(fd,0), RFIFOW(fd,2)); } - - // Send to char - memcpy(WBUFP(buf,0),RFIFOP(fd,0),RFIFOW(fd,2)); - WBUFW(buf,0)=0x2729; - charif_sendallwos(fd,buf,WBUFW(buf,2)); - if (buf) aFree(buf); } RFIFOSKIP(fd,RFIFOW(fd,2)); break; case 0x272a: // Receiving of map-server via char-server an unban request - if (RFIFOREST(fd) < 6) + if( RFIFOREST(fd) < 6 ) return 0; { - int acc; - acc = RFIFOL(fd,2); - sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = '%d'",login_db,login_db_account_id,acc); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - sql_res = mysql_store_result(&mysql_handle) ; - if (sql_res && mysql_num_rows(sql_res) > 0) { //Found a match - sprintf(tmpsql,"UPDATE `%s` SET `ban_until` = '0' WHERE `%s` = '%d'", login_db,login_db_account_id,acc); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + int account_id; + + account_id = RFIFOL(fd,2); + 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); } - if (sql_res) mysql_free_result(sql_res); RFIFOSKIP(fd,6); return 0; @@ -1194,33 +1197,36 @@ int parse_fromchar(int fd) { int account_id = RFIFOL(fd, 2); int char_id = RFIFOL(fd, 6); - int p; - sprintf(tmpsql, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'",reg_db, account_id); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - break; - } - sql_res = mysql_store_result(&mysql_handle) ; - if (!sql_res) { - break; - } + size_t off; + + 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); + 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 - p = 13; - while ((sql_row = mysql_fetch_row(sql_res)) && p < 9000) { - if (sql_row[0][0]) { - p+= sprintf(WFIFOP(fd,p), "%s", sql_row[0])+1; //We add 1 to consider the '\0' in place. - p+= sprintf(WFIFOP(fd,p), "%s", sql_row[1])+1; + 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(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(WFIFOP(fd,off), "%s", data)+1; } } - mysql_free_result(sql_res); - if (p >= 9000) + 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) = p; + WFIFOW(fd,2) = (uint16)off; WFIFOSET(fd,WFIFOW(fd,2)); RFIFOSKIP(fd,10); @@ -1258,53 +1264,39 @@ int parse_fromchar(int fd) int lan_subnetcheck(uint32 ip) { int i; - - for(i = 0; i < subnet_count; i++) { - if(subnet[i].subnet == (ip & subnet[i].mask)) { - return subnet[i].char_ip; - } - } - - return 0; + ARR_FIND( 0, subnet_count, i, subnet[i].subnet == (ip & subnet[i].mask) ); + return ( i < subnet_count ) ? subnet[i].char_ip : 0; } int login_ip_ban_check(uint32 ip) { uint8* p = (uint8*)&ip; - sprintf(tmpsql, "SELECT count(*) FROM `ipbanlist` WHERE `list` = '%d.*.*.*' OR `list` = '%d.%d.*.*' OR `list` = '%d.%d.%d.*' OR `list` = '%d.%d.%d.%d'", - p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]); - if (mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + 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; } - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; - if(!sql_row) { //Shouldn't happen, but just in case... - mysql_free_result(sql_res); - 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 - if (atoi(sql_row[0]) == 0) { //No ban - mysql_free_result(sql_res); - return 0; - } - // ip ban ok. - ShowInfo("Packet from banned ip : %d.%d.%d.%d\n", CONVIP(ip)); + ShowInfo("Packet from banned ip : %u.%u.%u.%u\n", CONVIP(ip)); - if (login_config.log_login) - { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', 'unknown','-3', 'ip banned')", loginlog_db, ip); - // query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } - mysql_free_result(sql_res); + 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; } @@ -1313,7 +1305,7 @@ int login_ip_ban_check(uint32 ip) //---------------------------------------------------------------------------------------- int parse_login(int fd) { - char t_uid[100]; + char esc_userid[NAME_LENGTH*2+1];// escaped username struct mmo_account account; int result, i; uint32 ipl = session[fd]->client_addr; @@ -1321,16 +1313,17 @@ int parse_login(int fd) ip2str(ipl, ip); - if (session[fd]->eof) { + if( session[fd]->eof ) + { do_close(fd); return 0; } - while (RFIFOREST(fd) >= 2) + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch(command) + switch( command ) { case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -1349,10 +1342,10 @@ int parse_login(int fd) case 0x0277: // New login packet (kRO 2006-04-24aSakexe langtype 0) case 0x02b0: // New login packet (kRO 2007-05-14aSakexe langtype 0) { - int packet_len = RFIFOREST(fd); + size_t packet_len = RFIFOREST(fd); - //Perform ip-ban check - if (login_config.ipban && login_ip_ban_check(ipl)) + // Perform ip-ban check + if( login_config.ipban && login_ip_ban_check(ipl) ) { WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; @@ -1376,37 +1369,38 @@ int parse_login(int fd) memset(&account, 0, sizeof(account)); account.version = RFIFOL(fd,2); - if (!account.version) account.version = 1; //Force some version... - memcpy(account.userid,RFIFOP(fd,6),NAME_LENGTH); account.userid[23] = '\0'; - memcpy(account.passwd,RFIFOP(fd,30),NAME_LENGTH); account.passwd[23] = '\0'; + if( !account.version ) + account.version = 1; //Force some version... + safestrncpy(account.userid, RFIFOP(fd,6), NAME_LENGTH);//## does it have to be nul-terminated? + safestrncpy(account.passwd, RFIFOP(fd,30), NAME_LENGTH);//## does it have to be nul-terminated? account.passwdenc = (command != 0x01dd) ? 0 : PASSWORDENC; - jstrescapecpy(t_uid, account.userid); + Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strlen(account.userid)); result = mmo_auth(&account, fd); - if (result == -1) { // auth success - if (login_config.min_level_to_connect > account.level) { + if( result == -1 ) + { // auth success + if( login_config.min_level_to_connect > account.level ) + { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); - } else { - if (login_config.log_login) { - sprintf(tmpsql,"INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s','100', 'login ok')", loginlog_db, ipl, t_uid); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } - if (account.level) + } + else + { + 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, ipl, esc_userid) ) + Sql_ShowDebug(sql_handle); + if( account.level ) ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", account.level, account.userid); else ShowStatus("Connection of the account '%s' accepted.\n", account.userid); server_num = 0; - WFIFOHEAD(fd,47+32*MAX_SERVERS); - for(i = 0; i < MAX_SERVERS; i++) { - if (server_fd[i] >= 0) { + WFIFOHEAD(fd, 47+32*MAX_SERVERS); + for( i = 0; i < MAX_SERVERS; ++i ) + { + if( session_isValid(server_fd[i]) ) + { // Advanced subnet check [LuzZza] uint32 subnet_char_ip = lan_subnetcheck(ipl); WFIFOL(fd,47+server_num*32) = htonl((subnet_char_ip) ? subnet_char_ip : server[i].ip); @@ -1443,7 +1437,9 @@ int parse_login(int fd) WFIFOSET(fd,3); } } - } else { // auth failed + } + else + { // auth failed if (login_config.log_login) { const char* error; @@ -1475,70 +1471,66 @@ int parse_login(int fd) default : error = "Unknown Error."; break; } - sprintf(tmpsql, "INSERT DELAYED INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%u', '%s', '%d','login failed : %s')", loginlog_db, ipl, t_uid, result, error); - - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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, ipl, esc_userid, result, error) ) + Sql_ShowDebug(sql_handle); } - if ((result == 1) && login_config.dynamic_pass_failure_ban && login_config.log_login) { // failed password - sprintf(tmpsql,"SELECT count(*) FROM `%s` WHERE `ip` = '%u' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", - loginlog_db, ipl, login_config.dynamic_pass_failure_ban_interval); //how many times filed account? in one ip. - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - //check query result - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //row fetching + 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, ipl, login_config.dynamic_pass_failure_ban_interval) )// how many times failed account? in one ip. + Sql_ShowDebug(sql_handle); - if (sql_row && (unsigned int)atoi(sql_row[0]) >= login_config.dynamic_pass_failure_ban_limit ) { + //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*)&ipl; - sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban: %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], login_config.dynamic_pass_failure_ban_duration, t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + 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); } - if(sql_res) mysql_free_result(sql_res); } - else if (result == -2){ //dynamic banned - add ip to ban list. + else if( result == -2 ) + {// dynamic banned - add ip to ban list. uint8* p = (uint8*)&ipl; - sprintf(tmpsql,"INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", (uint8)p[3], (uint8)p[2], (uint8)p[1], t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `ipbanlist`(`list`,`btime`,`rtime`,`reason`) VALUES ('%d.%d.%d.*', NOW() , NOW() + INTERVAL 1 MONTH ,'Dynamic banned user id : %s')", p[3], p[2], p[1], esc_userid) ) + Sql_ShowDebug(sql_handle); result = -3; - }else if(result == 6){ //not lastet version .. - //result = 5; } - - sprintf(tmpsql,"SELECT `ban_until` FROM `%s` WHERE `%s` = %s '%s'",login_db, login_db_userid, login_config.case_sensitive ? "BINARY" : "", t_uid); - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); + else if( result == 6 ) + {// not lastet version .. + //result = 5; } - sql_res = mysql_store_result(&mysql_handle) ; - sql_row = sql_res?mysql_fetch_row(sql_res):NULL; //cannot connect login failed WFIFOHEAD(fd,23); memset(WFIFOP(fd,0), '\0', 23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; - if (result == 6) { // 6 = Your are Prohibited to log in until %s - char tmpstr[20]; - time_t ban_until_time = (sql_row) ? atol(sql_row[0]) : 0; - strftime(tmpstr, 20, login_config.date_format, localtime(&ban_until_time)); tmpstr[19] = '\0'; - strncpy(WFIFOP(fd,3), tmpstr, 20); // ban timestamp goes here + if( result == 6 ) + {// 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 ban_until_time; + + Sql_GetData(sql_handle, 0, &data, NULL); + ban_until_time = (time_t)strtoul(data, NULL, 10); + Sql_FreeResult(sql_handle); + + strftime(WFIFOP(fd,3), 20, login_config.date_format, localtime(&ban_until_time)); + } } WFIFOSET(fd,23); - - if (sql_res) mysql_free_result(sql_res); } RFIFOSKIP(fd,packet_len); @@ -1548,19 +1540,20 @@ int parse_login(int fd) case 0x01db: // Sending request of the coding key { struct login_session_data* ld; - if (session[fd]->session_data) { + if( session[fd]->session_data ) + { ShowWarning("login: abnormal request of MD5 key (already opened session).\n"); set_eof(fd); return 0; } - ld = (struct login_session_data*)aCalloc(1, sizeof(struct login_session_data)); + CREATE(ld, struct login_session_data, 1); session[fd]->session_data = ld; // Creation of the coding key memset(ld->md5key, '\0', sizeof(ld->md5key)); ld->md5keylen = (uint16)(12 + rand() % 4); - for(i = 0; i < ld->md5keylen; i++) + for( i = 0; i < ld->md5keylen; ++i ) ld->md5key[i] = (char)(1 + rand() % 255); WFIFOHEAD(fd,4 + ld->md5keylen); @@ -1577,37 +1570,32 @@ int parse_login(int fd) if (RFIFOREST(fd) < 86) return 0; { + char esc_server_name[20*2+1]; char* server_name; uint32 server_ip; uint16 server_port; memset(&account, 0, sizeof(account)); - memcpy(account.userid,RFIFOP(fd,2),NAME_LENGTH); account.userid[23] = '\0'; - memcpy(account.passwd,RFIFOP(fd,26),NAME_LENGTH); account.passwd[23] = '\0'; + safestrncpy(account.userid, RFIFOP(fd,2), NAME_LENGTH); + safestrncpy(account.passwd, RFIFOP(fd,26), NAME_LENGTH); account.passwdenc = 0; - server_name = (char*)RFIFOP(fd,60); server_name[20] = '\0'; server_ip = ntohl(RFIFOL(fd,54)); server_port = ntohs(RFIFOW(fd,58)); - ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (ip: %s)\n", - server_name, CONVIP(server_ip), server_port, ip); - jstrescapecpy(t_uid, server_name); - if (login_config.log_login) - { - char t_login[50]; - jstrescapecpy(t_login,account.userid); - sprintf(tmpsql,"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, t_login, t_uid, t_uid, CONVIP(server_ip), server_port); - - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - } + server_name = (char*)RFIFOP(fd,60); + + Sql_EscapeStringLen(sql_handle, esc_server_name, server_name, strnlen(server_name, 20)); + Sql_EscapeStringLen(sql_handle, esc_userid, account.userid, strnlen(account.userid, NAME_LENGTH)); + + ShowInfo("Connection request of the char-server '%s' @ %d.%d.%d.%d:%d (account: '%s', pass: '%s', ip: '%s')\n", esc_server_name, CONVIP(server_ip), server_port, account.userid, account.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(&account, fd); - if (result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1) { - ShowStatus("Connection of the char-server '%s' accepted.\n", server_name); + if( result == -1 && account.sex == 2 && account.account_id < MAX_SERVERS && server_fd[account.account_id] == -1 ) + { + ShowStatus("Connection of the char-server '%s' accepted.\n", esc_server_name); memset(&server[account.account_id], 0, sizeof(struct mmo_char_server)); server[account.account_id].ip = ntohl(RFIFOL(fd,54)); server[account.account_id].port = ntohs(RFIFOW(fd,58)); @@ -1616,29 +1604,23 @@ int parse_login(int fd) server[account.account_id].maintenance = RFIFOW(fd,82); server[account.account_id].new_ = RFIFOW(fd,84); server_fd[account.account_id] = fd; - sprintf(tmpsql,"DELETE FROM `sstatus` WHERE `index`='%d'", account.account_id); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } - - sprintf(tmpsql,"INSERT INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", - account.account_id, t_uid,0); - //query - if(mysql_query(&mysql_handle, tmpsql)) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmpsql); - } + WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 0; WFIFOSET(fd,3); + session[fd]->func_parse = parse_fromchar; realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - + send_GM_accounts(fd); // send GM account to char-server - } else { + + if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `sstatus`(`index`,`name`,`user`) VALUES ( '%d', '%s', '%d')", account.account_id, esc_server_name, 0) ) + Sql_ShowDebug(sql_handle); + } + else + { + ShowNotice("Connection of the char-server '%s' REFUSED.\n", esc_server_name); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x2711; WFIFOB(fd,2) = 3; @@ -1668,12 +1650,12 @@ int parse_login(int fd) break; case 0x7532: // Request to end connection - ShowStatus ("End of connection (ip: %s)\n", ip); + ShowStatus("End of connection (ip: %s)\n", ip); set_eof(fd); break; default: - ShowStatus ("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); + ShowStatus("Abnormal end of connection (ip: %s): Unknown packet 0x%x\n", ip, RFIFOW(fd,0)); set_eof(fd); return 0; } @@ -1683,6 +1665,9 @@ int parse_login(int fd) return 0; } +//----------------------- +// Console Command Parser [Wizputer] +//----------------------- int parse_console(char* buf) { char command[256]; @@ -1691,20 +1676,22 @@ int parse_console(char* buf) sscanf(buf, "%[^\n]", command); - //login_log("Console command :%s\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 ) + 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 ){ + else + if( strcmpi("help", command) == 0 ) { printf(CL_BOLD"Help of commands:"CL_RESET"\n"); printf(" To shutdown the server:\n"); - printf(" 'shutdown|exit|qui|end'\n"); + printf(" 'shutdown|exit|quit|end'\n"); printf(" To know if server is alive:\n"); printf(" 'alive|status'\n"); } @@ -1788,10 +1775,8 @@ int login_lan_config_read(const char *lancfgName) //----------------------------------------------------- int ip_ban_flush(int tid, unsigned int tick, int id, int data) { - if(mysql_query(&mysql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()")) { - ShowSQL("DB error - %s\n",mysql_error(&mysql_handle)); - ShowDebug("at %s:%d - DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()\n", __FILE__,__LINE__); - } + if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") ) + Sql_ShowDebug(sql_handle); return 0; } @@ -1909,7 +1894,7 @@ void sql_config_read(const char* cfgName) else if (!strcmpi(w1, "login_server_ip")) strcpy(login_server_ip, w2); else if (!strcmpi(w1, "login_server_port")) - login_server_port = atoi(w2); + 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")) diff --git a/src/map/Makefile b/src/map/Makefile deleted file mode 100644 index dcb14bb3a..000000000 --- a/src/map/Makefile +++ /dev/null @@ -1,103 +0,0 @@ -all txt: txtobj map-server - -sql: sqlobj map-server_sql - -txtobj: - mkdir txtobj - -sqlobj: - mkdir sqlobj - -COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ - ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ - ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o \ - ../common/obj/utils.o ../common/obj/strlib.o ../common/obj/grfio.o \ - ../common/obj/mapindex.o ../common/obj/ers.o - -COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h \ - ../common/plugins.h ../common/lock.h ../common/nullpo.h ../common/malloc.h \ - ../common/showmsg.h ../common/utils.h ../common/strlib.h ../common/grfio.h \ - ../common/mapindex.h - -OBJECTS = obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/status.o obj/npc.o \ - obj/npc_chat.o obj/chat.o obj/path.o obj/itemdb.o obj/mob.o obj/script.o \ - obj/storage.o obj/skill.o obj/atcommand.o obj/charcommand.o obj/battle.o \ - obj/intif.o obj/trade.o obj/party.o obj/vending.o obj/guild.o obj/pet.o \ - obj/log.o obj/mail.o obj/date.o obj/irc.o obj/unit.o obj/mercenary.o \ - $(COMMON_OBJ) - -map-server: $(OBJECTS:obj/%=txtobj/%) - $(CC) -o ../../$@ $> $(LIBS) $(LIB_S) - -map-server_sql: $(OBJECTS:obj/%=sqlobj/%) - $(CC) -o ../../$@ $> $(LIB_S) - -txtobj/%.o: %.c - $(COMPILE.c) -DTXT_ONLY $(OUTPUT_OPTION) $< - -sqlobj/%.o: %.c - $(COMPILE.c) $(OUTPUT_OPTION) $< - -clean: - rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj GNUmakefile - -# DO NOT DELETE - -txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h irc.h $(COMMON_H) -txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) -txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h irc.h $(COMMON_H) -txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H) -txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) -txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) -txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) -txtobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) -txtobj/path.o: path.c map.h battle.h $(COMMON_H) -txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) -txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h date.h irc.h $(COMMON_H) -txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h irc.h $(COMMON_H) -txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) -txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h date.h $(COMMON_H) -txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) -txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) -txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H) -txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) -txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h irc.h $(COMMON_H) -txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) -txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) -txtobj/log.o: log.c log.h map.h $(COMMON_H) -txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -txtobj/date.o: date.c date.h $(COMMON_H) -txtobj/irc.o: irc.c irc.h map.h pc.h $(COMMON_H) -txtobj/unit.o: unit.c unit.h $(COMMON_H) -txtobj/mercenary.o: mercenary.c mercenary.h $(COMMON_H) - -sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h irc.h $(COMMON_H) -sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) -sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) -sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_H) -sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) -sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) -sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) -sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) -sqlobj/path.o: path.c map.h battle.h $(COMMON_H) -sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) -sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h date.h irc.h $(COMMON_H) -sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h irc.h $(COMMON_H) -sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) -sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h date.h $(COMMON_H) -sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) -sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) -sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_H) -sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) -sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h irc.h $(COMMON_H) -sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h irc.h $(COMMON_H) -sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) -sqlobj/mail.o: mail.c mail.h $(COMMON_H) -sqlobj/log.o: log.c log.h map.h $(COMMON_H) -sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -sqlobj/date.o: date.c date.h $(COMMON_H) -sqlobj/irc.o: irc.c irc.h map.h pc.h $(COMMON_H) -sqlobj/unit.o: unit.c unit.h $(COMMON_H) -sqlobj/mercenary.o: mercenary.c mercenary.h $(COMMON_H) diff --git a/src/map/Makefile.in b/src/map/Makefile.in new file mode 100644 index 000000000..1be112d9a --- /dev/null +++ b/src/map/Makefile.in @@ -0,0 +1,148 @@ + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + ALL_DEPENDS=txt sql + SQL_DEPENDS=obj_sql map-server_sql +else + ALL_TARGET=txt + SQL_DEPENDS=needs_mysql +endif + +HAVE_PCRE=@HAVE_PCRE@ +ifeq ($(HAVE_PCRE),yes) + PCRE_CFLAGS=-DPCRE_SUPPORT @PCRE_CFLAGS@ +else + PCRE_CFLAGS= +endif + + +##################################################################### +.PHONY : all txt sql clean help + +all: $(ALL_DEPENDS) + +txt: obj_txt map-server + +sql: $(SQL_DEPENDS) + +clean: + rm -rf *.o ../../map-server@EXEEXT@ ../../map-server_sql@EXEEXT@ obj_txt obj_sql + +help: +ifeq ($(HAVE_MYSQL),yes) + @echo "possible targets are 'sql' 'txt' 'all' 'clean' 'help'" + @echo "'sql' - map server (SQL version)" +else + @echo "possible targets are 'txt' 'all' 'clean' 'help'" +endif + @echo "'txt' - map 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 + +obj_txt: + -mkdir obj_txt + +obj_sql: + -mkdir obj_sql + +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o \ + ../common/obj/db.o ../common/obj/plugins.o ../common/obj/lock.o \ + ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o \ + ../common/obj/utils.o ../common/obj/strlib.o ../common/obj/grfio.o \ + ../common/obj/mapindex.o ../common/obj/ers.o + +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h \ + ../common/db.h ../common/plugins.h ../common/lock.h \ + ../common/nullpo.h ../common/malloc.h ../common/showmsg.h \ + ../common/utils.h ../common/strlib.h ../common/grfio.h \ + ../common/mapindex.h ../common/ers.h + +COMMON_SQL_OBJ = $(COMMON_OBJ) ../common/obj_sql/sql.o + +COMMON_SQL_H = $(COMMON_H) ../common/sql.h + +MAP_OBJ = obj/map.o obj/chrif.o obj/clif.o obj/pc.o obj/status.o obj/npc.o \ + obj/npc_chat.o obj/chat.o obj/path.o obj/itemdb.o obj/mob.o obj/script.o \ + obj/storage.o obj/skill.o obj/atcommand.o obj/charcommand.o obj/battle.o \ + obj/intif.o obj/trade.o obj/party.o obj/vending.o obj/guild.o obj/pet.o \ + obj/log.o obj/mail.o obj/date.o obj/irc.o obj/unit.o obj/mercenary.o + +map-server: $(MAP_OBJ:obj/%=obj_txt/%) $(COMMON_OBJ) + @CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ:obj/%=obj_txt/%) $(COMMON_OBJ) @LIBS@ @PCRE_LIBS@ + +map-server_sql: $(MAP_OBJ:obj/%=obj_sql/%) $(COMMON_SQL_OBJ) + @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_OBJ:obj/%=obj_sql/%) $(COMMON_SQL_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + +obj_txt/%.o: %.c + @CC@ @CFLAGS@ $(PCRE_CFLAGS) -DTXT_ONLY @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + +obj_sql/%.o: %.c + @CC@ @CFLAGS@ $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + +# DO NOT DELETE + +obj_txt/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h irc.h $(COMMON_H) +obj_txt/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +obj_txt/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h irc.h $(COMMON_H) +obj_txt/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H) +obj_txt/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +obj_txt/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +obj_txt/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +obj_txt/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +obj_txt/path.o: path.c map.h battle.h $(COMMON_H) +obj_txt/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +obj_txt/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h date.h irc.h $(COMMON_H) +obj_txt/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h irc.h $(COMMON_H) +obj_txt/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +obj_txt/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h date.h $(COMMON_H) +obj_txt/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +obj_txt/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +obj_txt/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +obj_txt/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H) +obj_txt/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +obj_txt/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h irc.h $(COMMON_H) +obj_txt/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +obj_txt/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +obj_txt/log.o: log.c log.h map.h $(COMMON_H) +obj_txt/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +obj_txt/date.o: date.c date.h $(COMMON_H) +obj_txt/irc.o: irc.c irc.h map.h pc.h $(COMMON_H) +obj_txt/unit.o: unit.c unit.h $(COMMON_H) +obj_txt/mercenary.o: mercenary.c mercenary.h $(COMMON_H) + +obj_sql/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h irc.h $(COMMON_SQL_H) +obj_sql/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_SQL_H) +obj_sql/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_SQL_H) +obj_sql/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_SQL_H) +obj_sql/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_SQL_H) +obj_sql/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_SQL_H) +obj_sql/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_SQL_H) +obj_sql/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_SQL_H) +obj_sql/path.o: path.c map.h battle.h $(COMMON_SQL_H) +obj_sql/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_SQL_H) +obj_sql/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h date.h irc.h $(COMMON_SQL_H) +obj_sql/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h irc.h $(COMMON_SQL_H) +obj_sql/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_SQL_H) +obj_sql/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h date.h $(COMMON_SQL_H) +obj_sql/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_SQL_H) +obj_sql/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_SQL_H) +obj_sql/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_SQL_H) +obj_sql/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_SQL_H) +obj_sql/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_SQL_H) +obj_sql/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h irc.h $(COMMON_SQL_H) +obj_sql/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h irc.h $(COMMON_SQL_H) +obj_sql/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_SQL_H) +obj_sql/mail.o: mail.c mail.h $(COMMON_SQL_H) +obj_sql/log.o: log.c log.h map.h $(COMMON_SQL_H) +obj_sql/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_SQL_H) +obj_sql/date.o: date.c date.h $(COMMON_SQL_H) +obj_sql/irc.o: irc.c irc.h map.h pc.h $(COMMON_SQL_H) +obj_sql/unit.o: unit.c unit.h $(COMMON_SQL_H) +obj_sql/mercenary.o: mercenary.c mercenary.h $(COMMON_SQL_H) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 428ff017d..3ddac9a9d 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -10,6 +10,7 @@ #include "../common/malloc.h" #include "../common/socket.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "atcommand.h" #include "log.h" @@ -273,6 +274,7 @@ ACMD_FUNC(checkmail); // [Valaris] ACMD_FUNC(listmail); // [Valaris] ACMD_FUNC(listnewmail); // [Valaris] ACMD_FUNC(readmail); // [Valaris] +ACMD_FUNC(deletemail); // [Valaris] ACMD_FUNC(sendmail); // [Valaris] ACMD_FUNC(sendprioritymail); // [Valaris] ACMD_FUNC(deletemail); // [Valaris] @@ -577,7 +579,7 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_ListMail, "@listmail", 1, atcommand_listmail }, // [Valaris] { AtCommand_ListNewMail, "@listnewmail", 1, atcommand_listmail }, // [Valaris] { AtCommand_ReadMail, "@readmail", 1, atcommand_readmail }, // [Valaris] - { AtCommand_DeleteMail, "@deletemail", 1, atcommand_readmail }, // [Valaris] + { AtCommand_DeleteMail, "@deletemail", 1, atcommand_deletemail }, // [Valaris] { AtCommand_SendMail, "@sendmail", 1, atcommand_sendmail }, // [Valaris] { AtCommand_SendPriorityMail, "@sendprioritymail",80, atcommand_sendmail }, // [Valaris] { AtCommand_RefreshOnline, "@refreshonline", 99, atcommand_refreshonline }, // [Valaris] @@ -7898,11 +7900,11 @@ int atcommand_listmail(const int fd, struct map_session_data* sd, const char* co nullpo_retr(-1, sd); - if(strlen(command)==12) + if(strlen(command)==12) // @listnewmail mail_check(sd,3); - else if(strlen(command)==9) + else if(strlen(command)==9) // @listmail mail_check(sd,2); - else + else // @checkmail mail_check(sd,1); return 0; } @@ -7926,10 +7928,31 @@ int atcommand_readmail(const int fd, struct map_session_data* sd, const char* co return 0; } - if(strlen(command)==11) - mail_delete(sd,index); - else - mail_read(sd,index); + mail_read(sd,index); + + return 0; +} + +int atcommand_deletemail(const int fd, struct map_session_data* sd, const char* command, const char* message) +{ + int index; + if(!mail_server_enable) + return 0; + + nullpo_retr(-1, sd); + + if (!message || !*message) { + clif_displaymessage(sd->fd,"You must specify a message number."); + return 0; + } + + index = atoi(message); + if (index < 1) { + clif_displaymessage(sd->fd,"Message number cannot be negative or zero."); + return 0; + } + + mail_delete(sd,index); return 0; } @@ -7954,7 +7977,7 @@ int atcommand_sendmail(const int fd, struct map_session_data* sd, const char* co return 0; } - if(strlen(command)==17) + if(strlen(command)==17) // @sendprioritymail mail_send(sd,name,text,1); else mail_send(sd,name,text,0); diff --git a/src/map/battle.c b/src/map/battle.c index 9264fbedf..2994dfa6a 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -8,6 +8,7 @@ #include "../common/showmsg.h" #include "../common/ers.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "map.h" #include "pc.h" diff --git a/src/map/charcommand.c b/src/map/charcommand.c index cfd3d59c8..88c32b307 100644 --- a/src/map/charcommand.c +++ b/src/map/charcommand.c @@ -6,6 +6,7 @@ #include "../common/timer.h" #include "../common/nullpo.h" #include "../common/showmsg.h" +#include "../common/utils.h" #include "log.h" #include "clif.h" diff --git a/src/map/clif.c b/src/map/clif.c index 5845ee102..ff6ccb9cf 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9,6 +9,7 @@ #include "../common/nullpo.h" #include "../common/showmsg.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "map.h" #include "chrif.h" diff --git a/src/map/guild.c b/src/map/guild.c index f9773d440..74cd0261a 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -9,6 +9,7 @@ #include "../common/showmsg.h" #include "../common/ers.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "map.h" #include "guild.h" @@ -1922,12 +1923,11 @@ int guild_save_sub(int tid,unsigned int tick,int id,int data) int guild_agit_break(struct mob_data *md) { // Run One NPC_Event[OnAgitBreak] - char *evname; + char* evname; if(!agit_flag) return 0; // Agit already End - evname=(char *)aMallocA((strlen(md->npc_event) + 1)*sizeof(char)); - strcpy(evname,md->npc_event); + evname = aStrdup(md->npc_event); // Now By User to Run [OnAgitBreak] NPC Event... // It's a little impossible to null point with player disconnect in this! // But Script will be stop, so nothing... diff --git a/src/map/intif.c b/src/map/intif.c index 9e7effef3..b6f457ee1 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -1497,7 +1497,7 @@ int intif_parse(int fd) case 0x3802: intif_parse_WisEnd(fd); break; case 0x3803: mapif_parse_WisToGM(fd); break; case 0x3804: intif_parse_Registers(fd); break; - case 0x3806: intif_parse_ChangeNameOk(fd); break; + case 0x3806: intif_parse_ChangeNameOk(fd); break; case 0x3810: intif_parse_LoadStorage(fd); break; case 0x3811: intif_parse_SaveStorage(fd); break; case 0x3818: intif_parse_LoadGuildStorage(fd); break; diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 1ba86cbc4..4ed47df61 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -615,369 +615,251 @@ static int itemdb_gendercheck(struct item_data *id) if (id->look == W_WHIP && id->type == IT_WEAPON) //Whips are always female-only return 0; - return (battle_config.ignore_items_gender?2:id->sex); + return (battle_config.ignore_items_gender) ? 2 : id->sex; } -#ifndef TXT_ONLY -/*====================================== - * SQL - *======================================*/ -static int itemdb_read_sqldb(void) -{ +/*========================================== + * processes one itemdb entry + *------------------------------------------*/ +static bool itemdb_parse_dbrow(char** str, char* source, int line) +{ + /* + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + | id | name_english | name_japanese | type | price_buy | price_sell | weight | attack | defence | range | slots | equip_jobs | equip_upper | equip_genders | equip_locations | weapon_level | equip_level | refineable | view | script | equip_script | unequip_script | + +----+--------------+---------------+------+-----------+------------+--------+--------+---------+-------+-------+------------+-------------+---------------+-----------------+--------------+-------------+------------+------+--------+--------------+----------------+ + */ unsigned short nameid; - struct item_data *id; - char script[65535 + 2 + 1]; // Maximum length of MySQL TEXT type (65535) + 2 bytes for curly brackets + 1 byte for terminator - char *item_db_name[] = { item_db_db, item_db2_db }; - long unsigned int ln = 0; - int i; - - // ---------- - - for (i = 0; i < 2; i++) { - sprintf(tmp_sql, "SELECT * FROM `%s`", item_db_name[i]); - - // Execute the query; if the query execution succeeded... - if (mysql_query(&mmysql_handle, tmp_sql) == 0) { - sql_res = mysql_store_result(&mmysql_handle); - - // If the storage of the query result succeeded... - if (sql_res) { - // Parse each row in the query result into sql_row - while ((sql_row = mysql_fetch_row(sql_res))) - { /*Table structure is: - 00 id - 01 name_english - 02 name_japanese - 03 type - 04 price_buy - 05 price_sell - 06 weight - 07 attack - 08 defence - 09 range - 10 slots - 11 equip_jobs - 12 equip_upper - 13 equip_genders - 14 equip_locations - 15 weapon_level - 16 equip_level - 17 refineable - 18 view - 19 script - 20 equip_script - 21 unequip_script - */ - nameid = atoi(sql_row[0]); - - // If the identifier is not within the valid range, process the next row - if (nameid == 0) - continue; - - ln++; - - // ---------- - id = itemdb_load(nameid); - - strncpy(id->name, sql_row[1], ITEM_NAME_LENGTH-1); - strncpy(id->jname, sql_row[2], ITEM_NAME_LENGTH-1); - - id->type = atoi(sql_row[3]); - if (id->type == IT_DELAYCONSUME) - { //Items that are consumed upon target confirmation - //(yggdrasil leaf, spells & pet lures) [Skotlex] - id->type = IT_USABLE; - id->flag.delay_consume=1; - } else //In case of an itemdb reload and the item type changed. - id->flag.delay_consume=0; - - // If price_buy is not NULL and price_sell is not NULL... - if ((sql_row[4] != NULL) && (sql_row[5] != NULL)) { - id->value_buy = atoi(sql_row[4]); - id->value_sell = atoi(sql_row[5]); - } - // If price_buy is not NULL and price_sell is NULL... - else if ((sql_row[4] != NULL) && (sql_row[5] == NULL)) { - id->value_buy = atoi(sql_row[4]); - id->value_sell = atoi(sql_row[4]) / 2; - } - // If price_buy is NULL and price_sell is not NULL... - else if ((sql_row[4] == NULL) && (sql_row[5] != NULL)) { - id->value_buy = atoi(sql_row[5]) * 2; - id->value_sell = atoi(sql_row[5]); - } - // If price_buy is NULL and price_sell is NULL... - if ((sql_row[4] == NULL) && (sql_row[5] == NULL)) { - id->value_buy = 0; - id->value_sell = 0; - } - - id->weight = atoi(sql_row[6]); - id->atk = (sql_row[7] != NULL) ? atoi(sql_row[7]) : 0; - id->def = (sql_row[8] != NULL) ? atoi(sql_row[8]) : 0; - id->range = (sql_row[9] != NULL) ? atoi(sql_row[9]) : 0; - id->slot = (sql_row[10] != NULL) ? atoi(sql_row[10]) : 0; - if (id->slot > MAX_SLOTS) - { - ShowWarning("itemdb_read_sqldb: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS); - id->slot = MAX_SLOTS; - } - itemdb_jobid2mapid(id->class_base, (sql_row[11] != NULL) ? (unsigned int)strtoul(sql_row[11], NULL, 0) : 0); - id->class_upper= (sql_row[12] != NULL) ? atoi(sql_row[12]) : 0; - id->sex = (sql_row[13] != NULL) ? atoi(sql_row[13]) : 0; - id->equip = (sql_row[14] != NULL) ? atoi(sql_row[14]) : 0; - if (!id->equip && itemdb_isequip2(id)) - { - ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); - id->type = 3; - } - id->wlv = (sql_row[15] != NULL) ? atoi(sql_row[15]) : 0; - id->elv = (sql_row[16] != NULL) ? atoi(sql_row[16]) : 0; - id->flag.no_refine = (sql_row[17] == NULL || atoi(sql_row[17]) == 1)?0:1; - id->look = (sql_row[18] != NULL) ? atoi(sql_row[18]) : 0; - id->view_id = 0; - id->sex = itemdb_gendercheck(id); //Apply gender filtering. - - // ---------- - - if (id->script) - script_free_code(id->script); - if (sql_row[19] != NULL) { - if (sql_row[19][0] == '{') - id->script = parse_script(sql_row[19],item_db_name[i], ln, 0); - else { - sprintf(script, "{%s}", sql_row[19]); - id->script = parse_script(script, item_db_name[i], ln, 0); - } - } else id->script = NULL; + struct item_data* id; - if (id->equip_script) - script_free_code(id->equip_script); - if (sql_row[20] != NULL) { - if (sql_row[20][0] == '{') - id->equip_script = parse_script(sql_row[20], item_db_name[i], ln, 0); - else { - sprintf(script, "{%s}", sql_row[20]); - id->equip_script = parse_script(script, item_db_name[i], ln, 0); - } - } else id->equip_script = NULL; + nameid = atoi(str[0]); + if(nameid <= 0) + return false; - if (id->unequip_script) - script_free_code(id->unequip_script); - if (sql_row[21] != NULL) { - if (sql_row[21][0] == '{') - id->unequip_script = parse_script(sql_row[21],item_db_name[i], ln, 0); - else { - sprintf(script, "{%s}", sql_row[21]); - id->unequip_script = parse_script(script, item_db_name[i], ln, 0); - } - } else id->unequip_script = NULL; - - // ---------- - - id->flag.available = 1; - id->flag.value_notdc = 0; - id->flag.value_notoc = 0; - } + //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View + id = itemdb_load(nameid); + safestrncpy(id->name, str[1], ITEM_NAME_LENGTH-1); + safestrncpy(id->jname, str[2], ITEM_NAME_LENGTH-1); + + id->type = atoi(str[3]); + if (id->type == IT_DELAYCONSUME) + { //Items that are consumed only after target confirmation + id->type = IT_USABLE; + id->flag.delay_consume = 1; + } else //In case of an itemdb reload and the item type changed. + id->flag.delay_consume = 0; + + id->value_buy = atoi(str[4]); + id->value_sell = atoi(str[5]); + if (id->value_buy < id->value_sell * 2) id->value_buy = id->value_sell * 2; // prevent exploit + if (id->value_buy == 0 && id->value_sell > 0) id->value_buy = id->value_sell * 2; + if (id->value_sell == 0 && id->value_buy > 0) id->value_sell = id->value_buy / 2; + + id->weight = atoi(str[6]); + id->atk = atoi(str[7]); + id->def = atoi(str[8]); + id->range = atoi(str[9]); + id->slot = atoi(str[10]); + + if (id->slot > MAX_SLOTS) + { + ShowWarning("itemdb_parse_dbrow: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS); + id->slot = MAX_SLOTS; + } + + itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); + id->class_upper = atoi(str[12]); + id->sex = atoi(str[13]); + id->equip = atoi(str[14]); + + if (!id->equip && itemdb_isequip2(id)) + { + ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); + id->type = IT_ETC; + } + + id->wlv = atoi(str[15]); + id->elv = atoi(str[16]); + id->flag.no_refine = atoi(str[17]) ? 0 : 1; //FIXME: verify this + id->look = atoi(str[18]); + + id->flag.available = 1; + id->flag.value_notdc = 0; + id->flag.value_notoc = 0; + id->view_id = 0; + id->sex = itemdb_gendercheck(id); //Apply gender filtering. - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, item_db_name[i]); - ln = 0; - } else { - ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if (id->script) + script_free_code(id->script); + if (id->equip_script) + script_free_code(id->equip_script); + if (id->unequip_script) + script_free_code(id->unequip_script); - // Free the query result - mysql_free_result(sql_res); - } else { - ShowSQL("DB error (%s) - %s\n",item_db_name[i], mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } + if (*str[19]) + id->script = parse_script(str[19], source, line, 0); + if (*str[20]) + id->equip_script = parse_script(str[20], source, line, 0); + if (*str[21]) + id->unequip_script = parse_script(str[21], source, line, 0); - return 0; + return true; } -#endif /* not TXT_ONLY */ /*========================================== * ƒAƒCƒeƒ€ƒf[ƒ^ƒx[ƒX‚Ì“Ç‚Ýž‚Ý *------------------------------------------*/ static int itemdb_readdb(void) { - FILE *fp; - char line[1024]; - int ln=0,lines=0; - int nameid,j; - char *str[32],*p,*np; - struct item_data *id; - int i=0; - char *filename[]={ "item_db.txt","item_db2.txt" }; - - for(i=0;i<2;i++){ - sprintf(line, "%s/%s", db_path, filename[i]); - fp=fopen(line,"r"); - if(fp==NULL){ - if(i>0) + char* filename[] = { "item_db.txt", "item_db2.txt" }; + int fi; + + for(fi = 0; fi < 2; fi++) + { + uint32 lines = 0, count = 0; + char line[1024]; + + char path[256]; + FILE* fp; + + sprintf(path, "%s/%s", db_path, filename[fi]); + fp = fopen(path, "r"); + if(fp == NULL) { + if(fi > 0) continue; - ShowFatalError("can't read %s\n",line); - exit(1); + return -1; } - lines=0; + // process rows one by one while(fgets(line, sizeof(line), fp)) { - lines++; - if(line[0]=='/' && line[1]=='/') - continue; - memset(str,0,sizeof(str)); - for(j=0,np=p=line;j<19 && p;j++){ - str[j]=p; - p=strchr(p,','); - if(p){ *p++=0; np=p; } - } - if(str[0]==NULL) - continue; + char *str[32], *p, *np; + int i; - nameid=atoi(str[0]); - if(nameid<=0) - continue; - if (j < 19) - { //Crash-fix on broken item lines. [Skotlex] - ShowWarning("Reading %s: Insufficient fields for item with id %d, skipping.\n", filename[i], nameid); + lines++; + if(line[0] == '/' && line[1] == '/') continue; - } - ln++; - - //ID,Name,Jname,Type,Price,Sell,Weight,ATK,DEF,Range,Slot,Job,Job Upper,Gender,Loc,wLV,eLV,refineable,View - id=itemdb_load(nameid); - strncpy(id->name, str[1], ITEM_NAME_LENGTH-1); - strncpy(id->jname, str[2], ITEM_NAME_LENGTH-1); - id->type=atoi(str[3]); - if (id->type == IT_DELAYCONSUME) - { //Items that are consumed upon target confirmation - //(yggdrasil leaf, spells & pet lures) [Skotlex] - id->type = IT_USABLE; - id->flag.delay_consume=1; - } else //In case of an itemdb reload and the item type changed. - id->flag.delay_consume=0; - + memset(str, 0, sizeof(str)); + for(i = 0, np = p = line; i < 19 && p; i++) { - int buy = atoi(str[4]), sell = atoi(str[5]); - // if buying price > selling price * 2 consider it valid and don't change it [celest] - if (buy && sell && buy > sell*2){ - id->value_buy = buy; - id->value_sell = sell; - } else { - // buy‚sell*2 ‚Í item_value_db.txt ‚ÅŽw’肵‚Ä‚‚¾‚³‚¢B - if (sell) { // sell’l‚ð—Dæ‚Æ‚·‚é - id->value_buy = sell*2; - id->value_sell = sell; - } else { - id->value_buy = buy; - id->value_sell = buy/2; - } + str[i] = p; + if ((p = strchr(p,',')) != NULL) { + *p++ = '\0'; np = p; } - // check for bad prices that can possibly cause exploits - if (id->value_buy*75/100 < id->value_sell*124/100) { - ShowWarning ("Item %s [%d] buying:%d < selling:%d\n", - id->name, id->nameid, id->value_buy*75/100, id->value_sell*124/100); - } - } - id->weight=atoi(str[6]); - id->atk=atoi(str[7]); - id->def=atoi(str[8]); - id->range=atoi(str[9]); - id->slot=atoi(str[10]); - if (id->slot > MAX_SLOTS) - { - ShowWarning("itemdb_readdb: Item %d (%s) specifies %d slots, but the server only supports up to %d\n", nameid, id->jname, id->slot, MAX_SLOTS); - id->slot = MAX_SLOTS; - } - itemdb_jobid2mapid(id->class_base, (unsigned int)strtoul(str[11],NULL,0)); - id->class_upper = atoi(str[12]); - id->sex = atoi(str[13]); - if(id->equip != atoi(str[14])){ - id->equip=atoi(str[14]); - } - if (!id->equip && itemdb_isequip2(id)) - { - ShowWarning("Item %d (%s) is an equipment with no equip-field! Making it an etc item.\n", nameid, id->jname); - id->type = 3; - } - id->wlv=atoi(str[15]); - id->elv=atoi(str[16]); - id->flag.no_refine = atoi(str[17])?0:1; //If the refine column is 1, no_refine is 0 - id->look=atoi(str[18]); - id->flag.available=1; - id->flag.value_notdc=0; - id->flag.value_notoc=0; - id->view_id=0; - id->sex = itemdb_gendercheck(id); //Apply gender filtering. - - if (id->script) { - script_free_code(id->script); - id->script=NULL; } - if (id->equip_script) { - script_free_code(id->equip_script); - id->equip_script=NULL; - } - if (id->unequip_script) { - script_free_code(id->unequip_script); - id->unequip_script=NULL; + + if (i < 19) { + ShowWarning("itemdb_readdb: Insufficient columns for item with id %d, skipping.\n", atoi(str[0])); + continue; } - if((p=strchr(np,'{'))==NULL) + if((p=strchr(np,'{')) == NULL) continue; - str[19] = p; //Script np = strchr(p,'}'); - while (np && np[1] && np[1] != ',') np = strchr(np+1,'}'); //Jump close brackets until the next field is found. if (!np || !np[1]) { - //Couldn't find the end of the script field. - id->script = parse_script(str[19],filename[i],lines,0); - continue; + continue; //Couldn't find the end of the script field. } np[1] = '\0'; //Set end of script - id->script = parse_script(str[19],filename[i],lines,0); - np+=2; //Skip to next field + np += 2; //Skip to next field if(!np || (p=strchr(np,'{'))==NULL) continue; - str[20] = p; //Equip Script np = strchr(p,'}'); - while (np && np[1] && np[1] != ',') np = strchr(np+1,'}'); //Jump close brackets until the next field is found. if (!np || !np[1]) { - //Couldn't find the end of the script field. - id->equip_script = parse_script(str[20],filename[i],lines,0); - continue; + continue; //Couldn't find the end of the script field. } - np[1] = '\0'; //Set end of script - id->equip_script = parse_script(str[20],filename[i],lines,0); - np+=2; //Skip comma, to next field + np += 2; //Skip comma, to next field if(!np || (p=strchr(np,'{'))==NULL) continue; - //Unequip script, last column. - id->unequip_script = parse_script(p,filename[i],lines,0); + str[21] = p; //Unequip script, last column. + + if (!itemdb_parse_dbrow(str, filename[fi], lines)) + continue; + + count++; } + fclose(fp); - if (ln > 0) { - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); + } + + return 0; +} + +#ifndef TXT_ONLY +/*====================================== + * item_db table reading + *======================================*/ +static int itemdb_read_sqldb(void) +{ + char* item_db_name[] = { item_db_db, item_db2_db }; + int fi; + + for (fi = 0; fi < 2; fi++) + { + uint32 lines = 0, count = 0; + + // retrieve all rows from the item database + if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) + { + Sql_ShowDebug(mmysql_handle); + continue; + } + + // process rows one by one + while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) + { + // wrap the result into a TXT-compatible format + char line[1024]; + char* str[22]; + char* p; + int i; + + lines++; + for (i = 0, p = line; i < 22; i++) + { + char* data; + size_t len; + Sql_GetData(mmysql_handle, i, &data, &len); + + if (data == NULL) + p[0] = '\0'; + else if (i >= 19 && data[0] != '{') { + sprintf(p, "{ %s }", data); len+= 4; + } else + strcpy(p, data); + str[i] = p; + p+= len + 1; + } + + if (!itemdb_parse_dbrow(str, item_db_name[fi], lines)) + continue; + + count++; } - ln=0; // reset to 0 + + // free the query result + Sql_FreeResult(mmysql_handle); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]); } + return 0; } +#endif /* not TXT_ONLY */ /*==================================== - * Removed item_value_db, don't re-add + * read all item-related databases *------------------------------------*/ static void itemdb_read(void) { diff --git a/src/map/log.c b/src/map/log.c index fdbb4470f..b5c4a3d9c 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -19,6 +19,8 @@ struct Log_Config log_config; char timestring[255]; time_t curtime; +static int should_log_item(int filter, int nameid, int amount); //log filter check + //FILTER OPTIONS //0 = Don't log //1 = Log any item @@ -58,104 +60,105 @@ int should_log_item(int filter, int nameid, int amount) int log_branch(struct map_session_data *sd) { -#ifndef TXT_ONLY - char t_name[NAME_LENGTH*2]; -#endif - FILE *logfp; - if(!log_config.enable_logs) return 0; + nullpo_retr(0, sd); + #ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", - log_config.log_branch_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), mapindex_id2name(sd->mapindex)); - if(mysql_query(&logmysql_handle, tmp_sql)) + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", log_config.log_branch_db, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); return 0; } - return 1; + SqlStmt_Free(stmt); } + else #endif - if((logfp=fopen(log_config.log_branch,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); - fclose(logfp); + { + FILE* logfp; + if((logfp = fopen(log_config.log_branch, "a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); + fclose(logfp); + } + return 1; } int log_pick_pc(struct map_session_data *sd, const char *type, int nameid, int amount, struct item *itm) { - FILE *logfp; - char *mapname; - nullpo_retr(0, sd); - //Should we log this item? [Lupus] - if (!should_log_item(log_config.filter,nameid, amount)) - return 0; //we skip logging this items set - they doesn't met our logging conditions [Lupus] - mapname = (char*)mapindex_id2name(sd->mapindex); - - if(mapname==NULL) - mapname=""; + if (!should_log_item(log_config.filter, nameid, amount)) + return 0; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] #ifndef TXT_ONLY if(log_config.sql_logs > 0) { - if (itm==NULL) { - //We log common item - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", - log_config.log_pick_db, sd->status.char_id, type, nameid, amount, mapname); + if (itm == NULL) { + //We log common item + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", + log_config.log_pick_db, sd->status.char_id, type, nameid, amount, mapindex_id2name(sd->mapindex)) ) + { + Sql_ShowDebug(logmysql_handle); + return 0; + } } else { - //We log Extended item - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", - log_config.log_pick_db, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); + //We log Extended item + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", + log_config.log_pick_db, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapindex_id2name(sd->mapindex)) ) + { + Sql_ShowDebug(logmysql_handle); + return 0; + } } + } + else +#endif + { + FILE* logfp; - if(mysql_query(&logmysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if((logfp = fopen(log_config.log_pick, "a+")) == NULL) return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + + if (itm == NULL) { + //We log common item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", + timestring, sd->status.char_id, type, nameid, amount, mapindex_id2name(sd->mapindex)); + + } else { + //We log Extended item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", + timestring, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapindex_id2name(sd->mapindex)); } - return 1; + fclose(logfp); } -#endif - if((logfp=fopen(log_config.log_pick,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - - if (itm==NULL) { - //We log common item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", - timestring, sd->status.char_id, type, nameid, amount, mapname); - - } else { - //We log Extended item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", - timestring, sd->status.char_id, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); - } - fclose(logfp); + return 1; //Logged } //Mob picked item int log_pick_mob(struct mob_data *md, const char *type, int nameid, int amount, struct item *itm) { - FILE *logfp; - char *mapname; + char* mapname; nullpo_retr(0, md); - //Should we log this item? [Lupus] - if (!should_log_item(log_config.filter,nameid, amount)) - return 0; //we skip logging this items set - they doesn't met our logging conditions [Lupus] + + if (!should_log_item(log_config.filter, nameid, amount)) + return 0; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] //either PLAYER or MOB (here we get map name and objects ID) mapname = map[md->bl.m].name; @@ -167,180 +170,200 @@ int log_pick_mob(struct mob_data *md, const char *type, int nameid, int amount, { if (itm==NULL) { //We log common item - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", - log_config.log_pick_db, md->class_, type, nameid, amount, mapname); + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%s')", + log_config.log_pick_db, md->class_, type, nameid, amount, mapname) ) + { + Sql_ShowDebug(logmysql_handle); + return 0; + } } else { //We log Extended item - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", - log_config.log_pick_db, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`) VALUES (NOW(), '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s')", + log_config.log_pick_db, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname) ) + { + Sql_ShowDebug(logmysql_handle); + return 0; + } } + } + else +#endif + { + FILE *logfp; - if(mysql_query(&logmysql_handle, tmp_sql)) - { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if((logfp=fopen(log_config.log_pick,"a+")) == NULL) return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + + if (itm==NULL) { + //We log common item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", + timestring, md->class_, type, nameid, amount, mapname); + + } else { + //We log Extended item + fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", + timestring, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); } - return 1; - } -#endif - if((logfp=fopen(log_config.log_pick,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - - if (itm==NULL) { - //We log common item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%s\n", - timestring, md->class_, type, nameid, amount, mapname); - - } else { - //We log Extended item - fprintf(logfp,"%s - %d\t%s\t%d,%d,%d,%d,%d,%d,%d,%s\n", - timestring, md->class_, type, itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], mapname); + fclose(logfp); } - fclose(logfp); + return 1; //Logged } int log_zeny(struct map_session_data *sd, char *type, struct map_session_data *src_sd, int amount) { -// FILE *logfp; - if(!log_config.enable_logs || (log_config.zeny!=1 && abs(amount)<log_config.zeny)) + if(!log_config.enable_logs || (log_config.zeny != 1 && abs(amount) < log_config.zeny)) return 0; nullpo_retr(0, sd); + #ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%s')", - log_config.log_zeny_db, sd->status.char_id, src_sd->status.char_id, type, amount, mapindex_id2name(sd->mapindex)); - if(mysql_query(&logmysql_handle, tmp_sql)) + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%d', '%s')", + log_config.log_zeny_db, sd->status.char_id, src_sd->status.char_id, type, amount, mapindex_id2name(sd->mapindex)) ) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(logmysql_handle); return 0; } - return 1; } + else #endif -// if((logfp=fopen(log_config.log_zeny,"a+")) == NULL) -// return 0; -// time(&curtime); -// strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); -// fprintf(logfp,"%s - %s[%d]\t%s[%d]\t%d\n", timestring, sd->status.name, sd->status.account_id, target_sd->status.name, target_sd->status.account_id, sd->deal.zeny); -// fclose(logfp); -// return 1; - return 0; + { + FILE* logfp; + if((logfp=fopen(log_config.log_zeny,"a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); + fclose(logfp); + } + + return 1; } int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp) { - FILE *logfp; - if(!log_config.enable_logs) return 0; + nullpo_retr(0, sd); + #ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)); - if(mysql_query(&logmysql_handle, tmp_sql)) + if (SQL_ERROR == Sql_Query(logmysql_handle, "INSERT DELAYED INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", + log_config.log_mvpdrop_db, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + Sql_ShowDebug(logmysql_handle); return 0; } - return 1; } + else #endif - if((logfp=fopen(log_config.log_mvpdrop,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); - fclose(logfp); - return 0; + { + FILE* logfp; + if((logfp=fopen(log_config.log_mvpdrop,"a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); + fclose(logfp); + } + + return 1; } -int log_atcommand(struct map_session_data *sd, const char *message) +int log_atcommand(struct map_session_data* sd, const char* message) { - FILE *logfp; -#ifndef TXT_ONLY - char t_name[NAME_LENGTH*2]; - char t_msg[CHAT_SIZE*2+1]; //These are the contents of an @ call, so there shouldn't be overflow danger here? -#endif - if(!log_config.enable_logs) return 0; + nullpo_retr(0, sd); + #ifndef TXT_ONLY if(log_config.sql_logs > 0) { + SqlStmt* stmt; + if (strlen(message) > CHAT_SIZE) { if (battle_config.error_log) - ShowError("log atcommand: Received message too long from player %s (%d:%d)!\n", - sd->status.name, sd->status.account_id, sd->status.char_id); + ShowError("log atcommand: Received message too long from player %s (%d:%d)!\n", sd->status.name, sd->status.account_id, sd->status.char_id); return 0; } - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", - log_config.log_gm_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), mapindex_id2name(sd->mapindex), jstrescapecpy(t_msg, (char *)message)); - if(mysql_query(&logmysql_handle, tmp_sql)) + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm_db, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex), message) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, strnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); return 0; } - return 1; + SqlStmt_Free(stmt); } + else #endif - if((logfp=fopen(log_config.log_gm,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d]: %s\n",timestring,sd->status.name,sd->status.account_id,message); - fclose(logfp); + { + FILE* logfp; + if((logfp = fopen(log_config.log_gm, "a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); + } + return 1; } -int log_npc(struct map_session_data *sd, const char *message) -{ //[Lupus] - FILE *logfp; -#ifndef TXT_ONLY - char t_name[NAME_LENGTH*2]; - char t_msg[255+1]; //it's 255 chars MAX. -#endif - +int log_npc(struct map_session_data* sd, const char* message) +{ if(!log_config.enable_logs) return 0; + nullpo_retr(0, sd); + #ifndef TXT_ONLY if(log_config.sql_logs > 0) { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES(NOW(), '%d', '%d', '%s', '%s', '%s') ", - log_config.log_npc_db, sd->status.account_id, sd->status.char_id, jstrescapecpy(t_name, sd->status.name), mapindex_id2name(sd->mapindex), jstrescapecpy(t_msg, (char *)message)); - if(mysql_query(&logmysql_handle, tmp_sql)) + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_npc_db, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex), message) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, strnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); return 0; } - return 1; + SqlStmt_Free(stmt); } + else #endif - if((logfp=fopen(log_config.log_npc,"a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d]: %s\n",timestring,sd->status.name,sd->status.account_id,message); - fclose(logfp); + { + FILE* logfp; + if((logfp = fopen(log_config.log_npc, "a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); + } + return 1; } - int log_chat(const char* type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) { + //FIXME: the actual filtering is being done by the calling code instead of in here, why!? + // Log CHAT (Global, Whisper, Party, Guild, Main chat) // LOGGING FILTERS [Lupus] //============================================================= @@ -353,42 +376,45 @@ int log_chat(const char* type, int type_id, int src_charid, int src_accid, const //16 - Log Main chat messages //32 - Don't log anything when WOE is on - FILE *logfp; -#ifndef TXT_ONLY - char t_charname[NAME_LENGTH*2]; - char t_msg[CHAT_SIZE*2+1]; //Chat line fully escaped, with an extra space just in case. -#endif - //Check ON/OFF if(log_config.chat <= 0) return 0; //Deactivated #ifndef TXT_ONLY - if(log_config.sql_logs > 0){ + if(log_config.sql_logs > 0) + { + SqlStmt* stmt; + if (strlen(message) > CHAT_SIZE) { if (battle_config.error_log) - ShowError("log chat: Received message too long from type %d (%d:%d)!\n", - type_id, src_accid, src_charid); + ShowError("log chat: Received message too long from type %d (%d:%d)!\n", type_id, src_accid, src_charid); return 0; } - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '%d', '%d', '%s', '%s')", - log_config.log_chat_db, type, type_id, src_charid, src_accid, map, x, y, jstrescapecpy(t_charname, dst_charname), jstrescapecpy(t_msg, message)); - - if(mysql_query(&logmysql_handle, tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%s', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", log_config.log_chat_db, type, type_id, src_charid, src_accid, map, x, y) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, strnlen(dst_charname, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, strnlen(message, CHAT_SIZE)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return 0; } - return 1; + SqlStmt_Free(stmt); } + else #endif - if((logfp = fopen(log_config.log_chat, "a+")) == NULL) - return 0; - time(&curtime); - strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s,%d,%d,%d,%s,%d,%d,%s,%s\n", - timestring, type, type_id, src_charid, src_accid, map, x, y, dst_charname, message); - fclose(logfp); + { + FILE* logfp; + if((logfp = fopen(log_config.log_chat, "a+")) == NULL) + return 0; + time(&curtime); + strftime(timestring, 254, "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, type, type_id, src_charid, src_accid, map, x, y, dst_charname, message); + fclose(logfp); + } + return 1; } diff --git a/src/map/log.h b/src/map/log.h index ee0b38beb..0065b77c0 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -9,12 +9,6 @@ struct map_session_data; struct mob_data; struct item; -#ifndef TXT_ONLY - -extern char db_server_logdb[32]; - -#endif //NOT TXT_ONLY - //New logs int log_pick_pc(struct map_session_data *sd, const char *type, int nameid, int amount, struct item *itm); int log_pick_mob(struct mob_data *md, const char *type, int nameid, int amount, struct item *itm); @@ -30,8 +24,6 @@ int log_mvpdrop(struct map_session_data *sd, int monster_id, int *log_mvp); int log_config_read(char *cfgName); -int should_log_item(int filter, int nameid, int amount); //log filter check - enum log_what { LOG_ALL = 0xFFF, LOG_TRADES = 0x002, diff --git a/src/map/mail.c b/src/map/mail.c index 8433fbada..6e6dc0a91 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -2,9 +2,6 @@ // For more information, see LICENCE in the main folder #ifndef TXT_ONLY -// Mail System for eAthena SQL -// Created by Valaris -// moved all strings to msg_athena.conf [Lupus] #include "../common/strlib.h" #include "../common/socket.h" @@ -27,318 +24,345 @@ int MAIL_CHECK_TIME = 120000; int mail_timer; -//extern char *msg_table[1000]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) -int mail_check(struct map_session_data *sd,int type) +/// type: 0 - mail check at login, silent if there aren't any new messages +/// 1 - @checkmail, just print the number of messages +/// 2 - @listmail, shows both read and unread messages +/// 3 - @listnewmail, shows only unread messages +int mail_check(struct map_session_data* sd, int type) { - int i = 0, new_ = 0, priority = 0; + int i = 0, new_ = 0, priority = 0; // counters char message[80]; nullpo_retr (0, sd); - sprintf(tmp_sql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` " - "FROM `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id`", mail_db, sd->status.account_id); - - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + // retrieve all existing messages for this player + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`to_account_id`,`from_char_name`,`read_flag`,`priority`,`check_flag` FROM `%s` WHERE `to_account_id` = %d ORDER by `message_id`", mail_db, sd->status.account_id) ) + { + Sql_ShowDebug(mail_handle); return 0; } - mail_res = mysql_store_result(&mail_handle); - if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - //clif_displaymessage(sd->fd,"You have no messages."); - clif_displaymessage(sd->fd, msg_txt(516)); + if( Sql_NumRows(mail_handle) == 0) + { + clif_displaymessage(sd->fd, msg_txt(516)); // "You have no messages." + Sql_FreeResult(mail_handle); + return 0; + } - mysql_free_result(mail_res); - return 0; + while( SQL_SUCCESS == Sql_NextRow(mail_handle) ) + { + char* data; + int message_id; + int to_account_id; + char from_char_name[NAME_LENGTH]; + bool read_flag, priority_flag, check_flag; + + Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data); + Sql_GetData(mail_handle, 1, &data, NULL); to_account_id = atoi(data); + Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name)); + Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data); + Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data); + Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data); + + i++; + + if( !check_flag ) + { + // mark this message as checked + if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) ) + Sql_ShowDebug(mail_handle); } - while ((mail_row = mysql_fetch_row(mail_res))) { - i++; - if(!atoi(mail_row[5])) { - sprintf(tmp_sql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( !read_flag ) + { + new_++; + if(priority_flag) + priority++; + + if( type == 2 || type == 3 ) + { + if( priority_flag ) + { + snprintf(message, 80, msg_txt(511), i, from_char_name); + clif_displaymessage(sd->fd, message); // "%d - From : %s (New - Priority)" } - } - - if(!atoi(mail_row[3])) { - new_++; - if(atoi(mail_row[4])) - priority++; - if(type==2 || type==3) { - if(atoi(mail_row[4])) { - snprintf(message, 80, msg_txt(511), i, mail_row[2]); - clif_displaymessage(sd->fd, message); - } else { - //sprintf(message, "%d - From : %s (New)", i, mail_row[2]); - snprintf(message, 80, msg_txt(512), i, mail_row[2]); - clif_displaymessage(sd->fd, message); - } + else + { + snprintf(message, 80, msg_txt(512), i, from_char_name); + clif_displaymessage(sd->fd, message); // "%d - From : %s (New)" } - } else if(type==2){ - snprintf(message, 80, msg_txt(513), i, mail_row[2]); - clif_displaymessage(sd->fd, message); } } + else if( type == 2 ) + { + snprintf(message, 80, msg_txt(513), i, from_char_name); + clif_displaymessage(sd->fd, message); // "%d - From : %s" + } + } - mysql_free_result(mail_res); - } else { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - - if(i>0 && new_>0 && type==1) { - //sprintf(message, "You have %d new messages.", new_); + Sql_FreeResult(mail_handle); + + if( new_ > 0 && (type == 0 || type == 1) ) + { sprintf(message, msg_txt(514), new_); - - clif_displaymessage(sd->fd, jstrescape(message)); - } - if(i>0 && new_>0 && priority>0 && type==1) { - //sprintf(message, "You have %d unread priority messages.", priority); - sprintf(message, msg_txt(515), priority); - clif_displaymessage(sd->fd, jstrescape(message)); + clif_displaymessage(sd->fd, message); // "You have %d unread messages." + if (priority > 0) + { + sprintf(message, msg_txt(515), priority); + clif_displaymessage(sd->fd, message); // "You have %d unread priority messages." + } } - if(!new_) { - //clif_displaymessage(sd->fd, "You have no new messages."); - clif_displaymessage(sd->fd, msg_txt(516)); + if( new_ == 0 && type != 0 ) + { + clif_displaymessage(sd->fd, msg_txt(516)); // "You have no unread messages." } return 0; } -int mail_read(struct map_session_data *sd, int message_id) +/// displays the selected message +int mail_read(struct map_session_data* sd, int index) { - + char* data; + int message_id; + char from_char_name[NAME_LENGTH]; char message[80]; + bool read_flag, priority_flag, check_flag; + char output[100]; - nullpo_retr (0, sd); + nullpo_retr(0, sd); - sprintf(tmp_sql,"SELECT `message_id`,`to_account_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1); + // retrieve the 'index'-th message + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`from_char_name`,`message`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) ) + { + Sql_ShowDebug(mail_handle); + return 0; + } - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( 0 == Sql_NumRows(mail_handle) ) + { + clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found." + Sql_FreeResult(mail_handle); return 0; - } - - mail_res = mysql_store_result(&mail_handle); - if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - //clif_displaymessage(sd->fd, "Message not found."); - clif_displaymessage(sd->fd, msg_txt(517)); - return 0; - } + } - if ((mail_row = mysql_fetch_row(mail_res))) { - if(!atoi(mail_row[6])) { - sprintf(tmp_sql,"UPDATE `%s` SET `check_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } + if( SQL_ERROR == Sql_NextRow(mail_handle) ) + { + Sql_ShowDebug(mail_handle); + Sql_FreeResult(mail_handle); + return 0; + } - //sprintf(message, "Reading message from %s", mail_row[2]); - sprintf(message, msg_txt(518), mail_row[2]); - clif_displaymessage(sd->fd, jstrescape(message)); + Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data); + Sql_GetData(mail_handle, 1, &data, NULL); safestrncpy(from_char_name, data, sizeof(from_char_name)); + Sql_GetData(mail_handle, 2, &data, NULL); safestrncpy(message, data, sizeof(message)); + Sql_GetData(mail_handle, 3, &data, NULL); read_flag = (bool) atoi(data); + Sql_GetData(mail_handle, 4, &data, NULL); priority_flag = (bool) atoi(data); + Sql_GetData(mail_handle, 5, &data, NULL); check_flag = (bool) atoi(data); - sprintf(message, "%s", mail_row[3]); - clif_displaymessage(sd->fd, jstrescape(message)); + Sql_FreeResult(mail_handle); - sprintf(tmp_sql,"UPDATE `%s` SET `read_flag`='1' WHERE `message_id`= \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } + // mark mail as checked + if( !check_flag ) + { + if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) ) + Sql_ShowDebug(mail_handle); + } - mysql_free_result(mail_res); + sprintf(output, msg_txt(518), from_char_name); + clif_displaymessage(sd->fd, output); // "Reading message from %s" + clif_displaymessage(sd->fd, message); - } else { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `read_flag` = 1 WHERE `message_id` = %d", mail_db, message_id) ) + { + Sql_ShowDebug(mail_handle); + } return 0; } -int mail_delete(struct map_session_data *sd, int message_id) +/// message deletion +int mail_delete(struct map_session_data* sd, int index) { + char* data; + int message_id; + bool read_flag, priority_flag, check_flag; + nullpo_retr (0, sd); - sprintf(tmp_sql,"SELECT `message_id`,`to_account_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = \"%d\" ORDER by `message_id` LIMIT %d, 1",mail_db,sd->status.account_id,message_id-1); + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `message_id`,`read_flag`,`priority`,`check_flag` from `%s` WHERE `to_account_id` = %d ORDER by `message_id` LIMIT %d, 1", mail_db, sd->status.account_id, index-1) ) + { + Sql_ShowDebug(mail_handle); + return 0; + } - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( 0 == Sql_NumRows(mail_handle) ) + { + clif_displaymessage(sd->fd, msg_txt(517)); // "Message not found." + Sql_FreeResult(mail_handle); return 0; - } - - mail_res = mysql_store_result(&mail_handle); - if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - //clif_displaymessage(sd->fd, "Message not found."); - clif_displaymessage(sd->fd, msg_txt(517)); - return 0; - } + } + + if( SQL_ERROR == Sql_NextRow(mail_handle) ) + { + Sql_ShowDebug(mail_handle); + Sql_FreeResult(mail_handle); + return 0; + } - if ((mail_row = mysql_fetch_row(mail_res))) { - if(!atoi(mail_row[2]) && atoi(mail_row[3])) { - mysql_free_result(mail_res); - //clif_displaymessage(sd->fd,"Cannot delete unread priority mail."); - clif_displaymessage(sd->fd,msg_txt(519)); + Sql_GetData(mail_handle, 0, &data, NULL); message_id = atoi(data); + Sql_GetData(mail_handle, 1, &data, NULL); read_flag = (bool)atoi(data); + Sql_GetData(mail_handle, 2, &data, NULL); priority_flag = (bool)atoi(data); + Sql_GetData(mail_handle, 3, &data, NULL); check_flag = (bool)atoi(data); - return 0; - } - if(!atoi(mail_row[4])) { - mysql_free_result(mail_res); - //clif_displaymessage(sd->fd,"You have received new mail, use @listmail before deleting."); - clif_displaymessage(sd->fd,msg_txt(520)); - return 0; - } - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `message_id` = \"%d\"", mail_db, atoi(mail_row[0])); - if(mysql_query(&mail_handle, tmp_sql) ) { - mysql_free_result(mail_res); - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - //else clif_displaymessage(sd->fd,"Message deleted."); - else clif_displaymessage(sd->fd,msg_txt(521)); - } + Sql_FreeResult(mail_handle); - mysql_free_result(mail_res); + if( !read_flag && priority_flag ) + { + clif_displaymessage(sd->fd,msg_txt(519)); // "Cannot delete unread priority mail." + return 0; + } - } else { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + if( !check_flag ) + { + clif_displaymessage(sd->fd,msg_txt(520)); // "You have received new mail, use @listmail before deleting." + return 0; } + if( SQL_ERROR == Sql_Query(mail_handle, "DELETE FROM `%s` WHERE `message_id` = %d", mail_db, message_id) ) + { + Sql_ShowDebug(mail_handle); + return 0; + } + + clif_displaymessage(sd->fd,msg_txt(521)); // "Message deleted." + return 0; } -int mail_send(struct map_session_data *sd, char *name, char *message, int flag) +/// for sending normal and priority messages +int mail_send(struct map_session_data* sd, char* name, char* message, int flag) { + SqlStmt* stmt; + nullpo_retr (0, sd); - if(pc_isGM(sd) < 80 && sd->mail_counter > 0) { - //clif_displaymessage(sd->fd,"You must wait 10 minutes before sending another message"); - clif_displaymessage(sd->fd,msg_txt(522)); + if( pc_isGM(sd) < 80 && sd->mail_counter > 0 ) + { + clif_displaymessage(sd->fd,msg_txt(522)); // "You must wait 10 minutes before sending another message" + return 0; + } + + if( strcmp(name,"*") == 0 && pc_isGM(sd) < 80 ) + { + clif_displaymessage(sd->fd, msg_txt(523)); // "Access Denied." return 0; } - if(strcmp(name,"*")==0) { - if(pc_isGM(sd) < 80) { - //clif_displaymessage(sd->fd, "Access Denied."); - clif_displaymessage(sd->fd, msg_txt(523)); + if( strcmp(name,"*") == 0 ) + { + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` != '%d' ORDER BY `account_id`", char_db, sd->status.account_id) ) + { + Sql_ShowDebug(mail_handle); return 0; } - else - sprintf(tmp_sql,"SELECT DISTINCT `account_id` FROM `%s` WHERE `account_id` <> '%d' ORDER BY `account_id`", char_db, sd->status.account_id); } else - sprintf(tmp_sql,"SELECT `account_id`,`name` FROM `%s` WHERE `name` = \"%s\"", char_db, jstrescape(name)); - - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - - mail_res = mysql_store_result(&mail_handle); - if(mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - //clif_displaymessage(sd->fd,"Character does not exist."); - clif_displaymessage(sd->fd,msg_txt(524)); + { + char name_[2*NAME_LENGTH]; + Sql_EscapeString(mail_handle, name_, name); + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT `account_id` FROM `%s` WHERE `name` = '%s'", char_db, name_) ) + { + Sql_ShowDebug(mail_handle); return 0; } + } - while ((mail_row = mysql_fetch_row(mail_res))) { - if(strcmp(name,"*")==0) { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`to_account_id`,`from_account_id`,`from_char_name`,`message`,`priority`)" - " VALUES ('%d', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), sd->status.account_id, sd->status.name, jstrescape(message), flag); - } - else { - sprintf(tmp_sql, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`)" - " VALUES ('%d', '%s', '%d', '%s', '%s', '%d')",mail_db, atoi(mail_row[0]), mail_row[1], sd->status.account_id, sd->status.name, jstrescape(message), flag); - if(pc_isGM(sd) < 80) - sd->mail_counter=5; - } + if( 0 == Sql_NumRows(mail_handle) ) + { + clif_displaymessage(sd->fd,msg_txt(524)); // "Character does not exist." + Sql_FreeResult(mail_handle); + return 0; + } - if(mysql_query(&mail_handle, tmp_sql) ) { - mysql_free_result(mail_res); - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - return 0; - } - } + stmt = SqlStmt_Malloc(mail_handle); + SqlStmt_Prepare(stmt, "INSERT DELAYED INTO `%s` (`to_account_id`,`to_char_name`,`from_account_id`,`from_char_name`,`message`,`priority`) VALUES (?, ?, '%d', ?, ?, '%d')", mail_db, sd->status.account_id, flag); + SqlStmt_BindParam(stmt, 1, SQLDT_STRING, name, strnlen(name, NAME_LENGTH)); + SqlStmt_BindParam(stmt, 2, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)); + SqlStmt_BindParam(stmt, 3, SQLDT_STRING, message, strnlen(message, 80)); + + while( SQL_SUCCESS == Sql_NextRow(mail_handle) ) + { + int id; + char* data; + Sql_GetData(mail_handle, 0, &data, NULL); id = atoi(data); + SqlStmt_BindParam(stmt, 0, SQLDT_INT, &id, sizeof(id)); + if( SQL_ERROR == SqlStmt_Execute(stmt) ) + SqlStmt_ShowDebug(stmt); } + Sql_FreeResult(mail_handle); + SqlStmt_Free(stmt); - //clif_displaymessage(sd->fd,"Mail has been sent."); - clif_displaymessage(sd->fd,msg_txt(525)); + if(pc_isGM(sd) < 80) + sd->mail_counter = 5; + + clif_displaymessage(sd->fd,msg_txt(525)); // "Mail has been sent." return 0; } -static int mail_check_timer_sub(struct map_session_data *sd, va_list va) +/// invoked every MAIL_CHECK_TIME ms, decreases the send blocking counter +static int mail_check_timer_sub(struct map_session_data* sd, va_list va) { - int id = va_arg(va, int); - if(pc_isGM(sd) < 80 && sd->mail_counter > 0) + if(sd->mail_counter > 0) sd->mail_counter--; - if(sd->status.account_id==id) - clif_displaymessage(sd->fd, msg_txt(526)); //you got new email. return 0; } -int mail_check_timer(int tid,unsigned int tick,int id,int data) +/// periodically checks for new messages and notifies about them +int mail_check_timer(int tid, unsigned int tick, int id, int data) { if(mail_timer != tid) return 0; - sprintf(tmp_sql,"SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db); + mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0); - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); + // fetch account ids of people who received new mail since the last iteration + if( SQL_ERROR == Sql_Query(mail_handle, "SELECT DISTINCT `to_account_id` FROM `%s` WHERE `read_flag` = '0' AND `check_flag` = '0'", mail_db) ) + { + Sql_ShowDebug(mail_handle); return 0; - } + } - mail_res = mysql_store_result(&mail_handle); + while( SQL_SUCCESS == Sql_NextRow(mail_handle) ) + { + char* id; + struct map_session_data* sd; + Sql_GetData(mail_handle, 0, &id, NULL); + if( (sd = map_id2sd(atoi(id))) != NULL ) + clif_displaymessage(sd->fd, msg_txt(526)); // "You have new mail." + } - if (mail_res) { - if (mysql_num_rows(mail_res) == 0) { - mysql_free_result(mail_res); - mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); - return 0; - } + Sql_FreeResult(mail_handle); - while ((mail_row = mysql_fetch_row(mail_res))) - clif_foreachclient(mail_check_timer_sub, atoi(mail_row[0])); - } + // decrease the send-blocking counter + clif_foreachclient(mail_check_timer_sub); - sprintf(tmp_sql,"UPDATE `%s` SET `check_flag`='1' WHERE `check_flag`= '0' ", mail_db); - if(mysql_query(&mail_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + // The 'check_flag' indicates whether the player was informed about the message. + // All online players were notified by the above code, and offline players will get the notice at next login. + // Therefore it is safe to simply set the flag to '1' for all existing mails. + if( SQL_ERROR == Sql_Query(mail_handle, "UPDATE `%s` SET `check_flag` = 1 WHERE `check_flag` = 0", mail_db) ) + Sql_ShowDebug(mail_handle); - mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); return 0; } int do_init_mail(void) { - add_timer_func_list(mail_check_timer,"mail_check_timer"); - mail_timer=add_timer(gettick()+MAIL_CHECK_TIME,mail_check_timer,0,0); + add_timer_func_list(mail_check_timer, "mail_check_timer"); + mail_timer = add_timer(gettick() + MAIL_CHECK_TIME, mail_check_timer, 0, 0); + return 0; } diff --git a/src/map/mail.h b/src/map/mail.h index fca124ae4..f753d827b 100644 --- a/src/map/mail.h +++ b/src/map/mail.h @@ -5,8 +5,8 @@ #define _MAIL_H_ int mail_check(struct map_session_data *sd, int type); -int mail_read(struct map_session_data *sd, int message_id); -int mail_delete(struct map_session_data *sd, int message_id); +int mail_read(struct map_session_data *sd, int index); +int mail_delete(struct map_session_data *sd, int index); int mail_send(struct map_session_data *sd, char *name, char *message, int flag); int do_init_mail(void); diff --git a/src/map/map.c b/src/map/map.c index 7c1ba6c4c..2476e0e0e 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -11,6 +11,7 @@ #include "../common/version.h" #include "../common/nullpo.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "map.h" #include "chrif.h" @@ -34,11 +35,8 @@ #include "mercenary.h" //[orn] #include "atcommand.h" #include "charcommand.h" - #include "log.h" - #include "irc.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -50,10 +48,20 @@ #endif #ifndef TXT_ONLY - #include "mail.h" +#endif -char tmp_sql[65535]=""; +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <math.h> +#ifndef _WIN32 +#include <unistd.h> +#endif + + +#ifndef TXT_ONLY char default_codepage[32] = ""; int map_server_port = 3306; @@ -61,9 +69,7 @@ char map_server_ip[32] = "127.0.0.1"; char map_server_id[32] = "ragnarok"; char map_server_pw[32] = "ragnarok"; char map_server_db[32] = "ragnarok"; -MYSQL mmysql_handle; -MYSQL_RES* sql_res; -MYSQL_ROW sql_row; +Sql* mmysql_handle; int db_use_sqldbs = 0; char item_db_db[32] = "item_db"; @@ -79,9 +85,7 @@ int log_db_port = 3306; char log_db_id[32] = "ragnarok"; char log_db_pw[32] = "ragnarok"; char log_db[32] = "log"; -MYSQL logmysql_handle; -MYSQL_RES* logsql_res; -MYSQL_ROW logsql_row; +Sql* logmysql_handle; // mail system int mail_server_enable = 0; @@ -91,9 +95,7 @@ char mail_server_id[32] = "ragnarok"; char mail_server_pw[32] = "ragnarok"; char mail_server_db[32] = "ragnarok"; char mail_db[32] = "mail"; -MYSQL mail_handle; -MYSQL_RES* mail_res; -MYSQL_ROW mail_row; +Sql* mail_handle; #endif /* not TXT_ONLY */ @@ -1096,7 +1098,7 @@ int map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y if (length) { //Adjust final position to fit in the given area. //TODO: Find an alternate method which does not requires a square root calculation. - k = sqrt(magnitude2); + k = (int)sqrt(magnitude2); mx1 = x0 + (x1 - x0)*length/k; my1 = y0 + (y1 - y0)*length/k; len_limit = MAGNITUDE2(x0,y0, mx1,my1); @@ -2951,43 +2953,30 @@ int inter_config_read(char *cfgName) *---------------------------------------*/ int map_sql_init(void) { - mysql_init(&mmysql_handle); + // main db connection + mmysql_handle = Sql_Malloc(); - //DB connection start ShowInfo("Connecting to the Map DB Server....\n"); - if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw, - map_server_db ,map_server_port, (char *)NULL, 0)) { - //pointer check - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - exit(1); - } - else { - ShowStatus("connect success! (Map Server Connection)\n"); - } + if( SQL_ERROR == Sql_Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) + exit(1); + ShowStatus("connect success! (Map Server Connection)\n"); - if(mail_server_enable) { // mail system [Valaris] - mysql_init(&mail_handle); - ShowInfo("Connecting to the Mail DB Server....\n"); - if(!mysql_real_connect(&mail_handle, mail_server_ip, mail_server_id, mail_server_pw, - mail_server_db ,mail_server_port, (char *)NULL, 0)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - exit(1); - } - if( strlen(default_codepage) > 0 ) { - sprintf( tmp_sql, "SET NAMES %s", default_codepage ); - if (mysql_query(&mail_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mail_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } - } + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) ) + Sql_ShowDebug(mmysql_handle); - if( strlen(default_codepage) > 0 ) { - sprintf( tmp_sql, "SET NAMES %s", default_codepage ); - if (mysql_query(&mmysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if(mail_server_enable) + { + // mail system + mail_handle = Sql_Malloc(); + + ShowInfo("Connecting to the Mail DB Server....\n"); + if( SQL_ERROR == Sql_Connect(mail_handle, mail_server_id, mail_server_pw, mail_server_ip, mail_server_port, mail_server_db) ) + exit(1); + + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(mail_handle, default_codepage) ) + Sql_ShowDebug(mail_handle); } return 0; @@ -2995,13 +2984,15 @@ int map_sql_init(void) int map_sql_close(void) { - mysql_close(&mmysql_handle); ShowStatus("Close Map DB Connection....\n"); + Sql_Free(mmysql_handle); + mmysql_handle = NULL; if (log_config.sql_logs) { - mysql_close(&logmysql_handle); ShowStatus("Close Log DB Connection....\n"); + Sql_Free(logmysql_handle); + logmysql_handle = NULL; } return 0; @@ -3009,25 +3000,18 @@ int map_sql_close(void) int log_sql_init(void) { - mysql_init(&logmysql_handle); + // log db connection + logmysql_handle = Sql_Malloc(); - //DB connection start ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db,log_db_ip); - if(!mysql_real_connect(&logmysql_handle, log_db_ip, log_db_id, log_db_pw, - log_db ,log_db_port, (char *)NULL, 0)) { - //pointer check - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - exit(1); - } - + if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db) ) + exit(1); ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db); - if( strlen(default_codepage) > 0 ) { - sprintf( tmp_sql, "SET NAMES %s", default_codepage ); - if (mysql_query(&logmysql_handle, tmp_sql)) { - ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } - } + + if( strlen(default_codepage) > 0 ) + if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) + Sql_ShowDebug(logmysql_handle); + return 0; } @@ -3037,31 +3021,25 @@ int log_sql_init(void) int map_sql_ping(int tid, unsigned int tick, int id, int data) { ShowInfo("Pinging SQL server to keep connection alive...\n"); - mysql_ping(&mmysql_handle); + Sql_Ping(mmysql_handle); if (log_config.sql_logs) - mysql_ping(&logmysql_handle); + Sql_Ping(logmysql_handle); if(mail_server_enable) - mysql_ping(&mail_handle); + Sql_Ping(mail_handle); return 0; } int sql_ping_init(void) { - int connection_timeout, connection_ping_interval; + uint32 connection_timeout, connection_ping_interval; - // set a default value first + // set a default value connection_timeout = 28800; // 8 hours // ask the mysql server for the timeout value - if (!mysql_query(&mmysql_handle, "SHOW VARIABLES LIKE 'wait_timeout'") - && (sql_res = mysql_store_result(&mmysql_handle)) != NULL) { - sql_row = mysql_fetch_row(sql_res); - if (sql_row) - connection_timeout = atoi(sql_row[1]); - if (connection_timeout < 60) - connection_timeout = 60; - mysql_free_result(sql_res); - } + Sql_GetTimeout(mmysql_handle, &connection_timeout); + if (connection_timeout < 60) + connection_timeout = 60; // establish keepalive connection_ping_interval = connection_timeout - 30; // 30-second reserve diff --git a/src/map/map.h b/src/map/map.h index 15a0ece81..cd28f0f14 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -795,7 +795,7 @@ struct map_session_data { char fakename[NAME_LENGTH]; // fake names [Valaris] #ifndef TXT_ONLY - int mail_counter; // mail counter for mail system [Valaris] + int mail_counter; // mail counter for mail system (antiflood protection) #endif int duel_group; // duel vars [LuzZza] @@ -1396,37 +1396,6 @@ extern char *MSG_CONF_NAME; extern char *map_server_dns; -#ifndef TXT_ONLY - -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <mysql.h> - -extern char tmp_sql[65535]; - -extern int db_use_sqldbs; -extern MYSQL mmysql_handle; -extern MYSQL_RES* sql_res ; -extern MYSQL_ROW sql_row ; - -extern MYSQL logmysql_handle; -extern MYSQL_RES* logsql_res ; -extern MYSQL_ROW logsql_row ; - -extern int mail_server_enable; -extern MYSQL mail_handle; -extern MYSQL_RES* mail_res ; -extern MYSQL_ROW mail_row ; - -extern char item_db_db[32]; -extern char item_db2_db[32]; -extern char mob_db_db[32]; -extern char mob_db2_db[32]; -extern char char_db[32]; -extern char mail_db[32]; - -#endif /* not TXT_ONLY */ //Useful typedefs from jA [Skotlex] typedef struct map_session_data TBL_PC; typedef struct npc_data TBL_NPC; @@ -1444,4 +1413,24 @@ typedef struct homun_data TBL_HOM; extern int lowest_gm_level; extern char main_chat_nick[16]; +#ifndef TXT_ONLY + +#include "../common/sql.h" + +extern int db_use_sqldbs; +extern int mail_server_enable; + +extern Sql* mmysql_handle; +extern Sql* logmysql_handle; +extern Sql* mail_handle; + +extern char item_db_db[32]; +extern char item_db2_db[32]; +extern char mob_db_db[32]; +extern char mob_db2_db[32]; +extern char char_db[32]; +extern char mail_db[32]; + +#endif /* not TXT_ONLY */ + #endif /* _MAP_H_ */ diff --git a/src/map/mob.c b/src/map/mob.c index 86d60a152..b5c83413c 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -9,6 +9,7 @@ #include "../common/showmsg.h" #include "../common/ers.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "map.h" #include "clif.h" @@ -3210,7 +3211,10 @@ static unsigned int mob_drop_adjust(int rate, int rate_adjust, unsigned short ra return cap_value(rate,rate_min,rate_max); } -int mob_parse_dbrow(char** str) +/*========================================== + * processes one mobdb entry + *------------------------------------------*/ +static bool mob_parse_dbrow(char** str) { struct mob_db *db; struct status_data *status; @@ -3220,15 +3224,15 @@ int mob_parse_dbrow(char** str) class_ = str[0] ? atoi(str[0]) : 0; if (class_ == 0) - return 0; //Leave blank lines alone... [Skotlex] + return false; //Leave blank lines alone... [Skotlex] if (class_ <= 1000 || class_ > MAX_MOB_DB) { ShowWarning("Mob with ID: %d not loaded. ID must be in range [%d-%d]\n", class_, 1000, MAX_MOB_DB); - return 0; + return false; } if (pcdb_checkid(class_)) { ShowWarning("Mob with ID: %d not loaded. That ID is reserved for player classes.\n"); - return 0; + return false; } if (mob_db_data[class_] == NULL) @@ -3432,7 +3436,7 @@ int mob_parse_dbrow(char** str) } } - return 1; + return true; } /*========================================== @@ -3440,83 +3444,113 @@ int mob_parse_dbrow(char** str) *------------------------------------------*/ static int mob_readdb(void) { - FILE *fp; - char line[1024]; - char *filename[]={ "mob_db.txt","mob_db2.txt" }; - int i, fi; - unsigned int ln = 0; + char* filename[] = { "mob_db.txt", "mob_db2.txt" }; + int fi; - for(fi = 0; fi < 2; fi++) { - sprintf(line, "%s/%s", db_path, filename[fi]); - fp = fopen(line, "r"); + for(fi = 0; fi < 2; fi++) + { + uint32 lines = 0, count = 0; + char line[1024]; + char path[256]; + FILE* fp; + + sprintf(path, "%s/%s", db_path, filename[fi]); + fp = fopen(path, "r"); if(fp == NULL) { if(fi > 0) continue; return -1; } + // process rows one by one while(fgets(line, sizeof(line), fp)) { char *str[38+2*MAX_MOB_DROP], *p, *np; + int i; + lines++; if(line[0] == '/' && line[1] == '/') continue; - for(i = 0, p = line; i < 38 + 2*MAX_MOB_DROP; i++) { + for(i = 0, p = line; i < 38 + 2*MAX_MOB_DROP; i++) + { + str[i] = p; if((np = strchr(p, ',')) != NULL) { - str[i] = p; *np = 0; p = np + 1; - } else - str[i] = p; + *np = '\0'; p = np + 1; + } } if(i < 38 + 2*MAX_MOB_DROP) { - ShowWarning("mob_readdb: Insufficient columns for mob with ID: %d\n", str[0] ? atoi(str[0]) : 0); + ShowWarning("mob_readdb: Insufficient columns for mob with id: %d, skipping.\n", atoi(str[0])); continue; } if (!mob_parse_dbrow(str)) continue; - ln++; // counts the number of correctly parsed entries + count++; } + fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, filename[fi]); - ln = 0; + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename[fi]); } + return 0; } #ifndef TXT_ONLY /*========================================== - * SQL reading + * mob_db table reading *------------------------------------------*/ static int mob_read_sqldb(void) { - char *mob_db_name[] = { mob_db_db, mob_db2_db }; + char* mob_db_name[] = { mob_db_db, mob_db2_db }; int fi; - unsigned int ln = 0; - for (fi = 0; fi < 2; fi++) { - sprintf (tmp_sql, "SELECT * FROM `%s`", mob_db_name[fi]); - if (mysql_query(&mmysql_handle, tmp_sql)) { - ShowSQL("DB error (%s) - %s\n", mob_db_name[fi], mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + for (fi = 0; fi < 2; fi++) + { + uint32 lines = 0, count = 0; + + // retrieve all rows from the mob database + if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) + { + Sql_ShowDebug(mmysql_handle); continue; } - sql_res = mysql_store_result(&mmysql_handle); - if (sql_res) { - while((sql_row = mysql_fetch_row(sql_res))){ - - if (!mob_parse_dbrow(sql_row)) - continue; + + // process rows one by one + while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) + { + // wrap the result into a TXT-compatible format + char line[1024]; + char* str[38+2*MAX_MOB_DROP]; + char* p; + int i; + + lines++; + for(i = 0, p = line; i < 38 + 2*MAX_MOB_DROP; i++) + { + char* data; + size_t len; + Sql_GetData(mmysql_handle, i, &data, &len); - ln++; // counts the number of correctly parsed entries + strcpy(p, data); + str[i] = p; + p+= len + 1; } - mysql_free_result(sql_res); - ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", ln, mob_db_name[fi]); - ln = 0; + if (!mob_parse_dbrow(str)) + continue; + + count++; } + + // free the query result + Sql_FreeResult(mmysql_handle); + + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); + count = 0; } return 0; } diff --git a/src/map/npc.c b/src/map/npc.c index 4adf4b946..b469878eb 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -6,6 +6,7 @@ #include "../common/nullpo.h" #include "../common/malloc.h" #include "../common/showmsg.h" +#include "../common/utils.h" #include "../common/ers.h" #include "../common/db.h" #include "map.h" diff --git a/src/map/party.c b/src/map/party.c index e4b960342..284f00a77 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -7,6 +7,7 @@ #include "../common/nullpo.h" #include "../common/malloc.h" #include "../common/showmsg.h" +#include "../common/utils.h" #include "party.h" #include "atcommand.h" //msg_txt() diff --git a/src/map/pc.c b/src/map/pc.c index 3dd2289c3..d6a41db37 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -8,6 +8,7 @@ #include "../common/showmsg.h" #include "../common/socket.h" // RFIFO*() #include "../common/timer.h" +#include "../common/utils.h" #include "atcommand.h" // get_atcommand_level() #include "battle.h" // battle_config @@ -742,7 +743,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t #ifndef TXT_ONLY if(mail_server_enable) - mail_check(sd,1); // check mail at login [Valaris] + mail_check(sd,0); // check mail at login [Valaris] #endif // message of the limited time of the account diff --git a/src/map/pet.c b/src/map/pet.c index b593cbdff..9bebf27bc 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -6,6 +6,7 @@ #include "../common/nullpo.h" #include "../common/malloc.h" #include "../common/showmsg.h" +#include "../common/utils.h" #include "../common/ers.h" #include "pc.h" diff --git a/src/map/script.c b/src/map/script.c index d423d433e..0a5b5fbc0 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -226,13 +226,10 @@ int potion_hp=0, potion_per_hp=0, potion_sp=0, potion_per_sp=0; int potion_target=0; #if !defined(TXT_ONLY) && defined(MAPREGSQL) -// [zBuffer] SQL Mapreg Saving/Loading Database Declaration char mapregsql_db[32] = "mapreg"; char mapregsql_db_varname[32] = "varname"; char mapregsql_db_index[32] = "index"; char mapregsql_db_value[32] = "value"; -char tmp_sql[65535]; -// -------------------------------------------------------- #endif int get_com(unsigned char *script,int *pos); @@ -3222,85 +3219,76 @@ void run_script_main(struct script_state *st) /*========================================== * ƒ}ƒbƒv•Ï”‚Ì•ÏX *------------------------------------------*/ -int mapreg_setreg(int num,int val) +int mapreg_setreg(int num, int val) { #if !defined(TXT_ONLY) && defined(MAPREGSQL) - int i=num>>24; - char *name=str_buf+str_data[num&0x00ffffff].str; - char tmp_str[64]; -#endif + int i = num >> 24; + char* name = str_buf + str_data[num&0x00ffffff].str; - if(val!=0) { + if( val != 0 ) { if(idb_put(mapreg_db,num,(void*)val)) ; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) else if(name[1] != '@') { - sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%d')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,val); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + char tmp_str[32*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%d')", mapregsql_db, mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, tmp_str, i, val) ) + Sql_ShowDebug(mmysql_handle); } -#endif - } else { // [zBuffer] -#if !defined(TXT_ONLY) && defined(MAPREGSQL) + } else { // val == 0 if(name[1] != '@') { // Remove from database because it is unused. - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_varname, name, mapregsql_db_index, i) ) + Sql_ShowDebug(mmysql_handle); } -#endif idb_remove(mapreg_db,num); } +#else + if(val != 0) + idb_put(mapreg_db,num,(void*)val); + else + idb_remove(mapreg_db,num); +#endif - mapreg_dirty=1; + mapreg_dirty = 1; return 1; } /*========================================== * •¶Žš—ñŒ^ƒ}ƒbƒv•Ï”‚Ì•ÏX *------------------------------------------*/ -int mapreg_setregstr(int num,const char *str) +int mapreg_setregstr(int num, const char* str) { - char *p; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - char tmp_str[64]; - char tmp_str2[512]; - int i=num>>24; // [zBuffer] - char *name=str_buf+str_data[num&0x00ffffff].str; -#endif - - if( str==NULL || *str==0 ){ #if !defined(TXT_ONLY) && defined(MAPREGSQL) + int i = num >> 24; + char* name = str_buf + str_data[num&0x00ffffff].str; + + if( str==NULL || *str==0 ) { if(name[1] != '@') { - sprintf(tmp_sql,"DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_varname, name, mapregsql_db_index, i) ) + Sql_ShowDebug(mmysql_handle); } -#endif idb_remove(mapregstr_db,num); - mapreg_dirty=1; + mapreg_dirty = 1; return 1; } - p=(char *)aMallocA((strlen(str)+1)*sizeof(char)); - strcpy(p,str); - if (idb_put(mapregstr_db,num,p)) + if (idb_put(mapregstr_db,num, aStrdup(str))) ; -#if !defined(TXT_ONLY) && defined(MAPREGSQL) - else if(name[1] != '@'){ //put returned null, so we must insert. + else if(name[1] != '@') { //put returned null, so we must insert. // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] - sprintf(tmp_sql,"INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%s')",mapregsql_db,mapregsql_db_varname,mapregsql_db_index,mapregsql_db_value,jstrescapecpy(tmp_str,name),i,jstrescapecpy(tmp_str2,p)); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + char tmp_str[32*2+1]; + char tmp_str2[255*2+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`%s`,`%s`,`%s`) VALUES ('%s','%d','%s')", mapregsql_db, mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, tmp_str, i, tmp_str2) ) + Sql_ShowDebug(mmysql_handle); } +#else + if( str==NULL || *str==0 ) + idb_remove(mapregstr_db,num); + else + idb_put(mapregstr_db,num,aStrdup(str)); #endif - mapreg_dirty=1; + + mapreg_dirty = 1; return 1; } @@ -3310,83 +3298,87 @@ int mapreg_setregstr(int num,const char *str) static int script_load_mapreg(void) { #if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp; + FILE* fp; char line[1024]; - if( (fp=fopen(mapreg_txt,"rt"))==NULL ) + if( (fp=fopen(mapreg_txt,"rt")) == NULL ) return -1; while(fgets(line,sizeof(line),fp)) { - char buf1[256],buf2[1024],*p; + char buf1[256],buf2[1024]; + char* p; int n,v,s,i; if( sscanf(line,"%255[^,],%d\t%n",buf1,&i,&n)!=2 && (i=0,sscanf(line,"%[^\t]\t%n",buf1,&n)!=1) ) continue; - if( buf1[strlen(buf1)-1]=='$' ){ - if( sscanf(line+n,"%[^\n\r]",buf2)!=1 ){ - ShowError("%s: %s broken data !\n",mapreg_txt,buf1); + if( buf1[strlen(buf1)-1] == '$' ) { + if( sscanf(line + n, "%[^\n\r]", buf2) != 1 ) { + ShowError("%s: %s broken data !\n", mapreg_txt, buf1); continue; } - p=(char *)aMallocA((strlen(buf2) + 1)*sizeof(char)); - strcpy(p,buf2); - s= add_str(buf1); - idb_put(mapregstr_db,(i<<24)|s,p); - }else{ - if( sscanf(line+n,"%d",&v)!=1 ){ - ShowError("%s: %s broken data !\n",mapreg_txt,buf1); + p = aStrdup(buf2); + s = add_str(buf1); + idb_put(mapregstr_db, (i<<24)|s, p); + } else { + if( sscanf(line + n, "%d", &v) != 1 ) { + ShowError("%s: %s broken data !\n", mapreg_txt, buf1); continue; } - s= add_str(buf1); - idb_put(mapreg_db,(i<<24)|s,(void*)v); + s = add_str(buf1); + idb_put(mapreg_db, (i<<24)|s, (void*)v); } } fclose(fp); - mapreg_dirty=0; + + mapreg_dirty = 0; return 0; #else - // SQL mapreg code start [zBuffer] /* - 0 1 2 - +-------------------------+ - | varname | index | value | - +-------------------------+ - */ - unsigned int perfomance = (unsigned int)time(NULL); - sprintf(tmp_sql,"SELECT * FROM `%s`",mapregsql_db); - ShowInfo("Querying script_load_mapreg ...\n"); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); + 0 1 2 + +-------------------------+ + | varname | index | value | + +-------------------------+ + */ + + SqlStmt* stmt = SqlStmt_Malloc(mmysql_handle); + char varname[32+1]; + int index; + char value[255+1]; + uint32 length; + + if ( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `%s`, `%s`, `%s` FROM `%s`", mapregsql_db_varname, mapregsql_db_index, mapregsql_db_value, mapregsql_db) + || SQL_ERROR == SqlStmt_Execute(stmt) + ) { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); return -1; } - ShowInfo("Success! Returning results ...\n"); - sql_res = mysql_store_result(&mmysql_handle); - if (sql_res) { - while ((sql_row = mysql_fetch_row(sql_res))) { - char buf1[33], *p = NULL; - int i,v,s; - strcpy(buf1,sql_row[0]); - if( buf1[strlen(buf1)-1]=='$' ){ - i = atoi(sql_row[1]); - p=(char *)aMallocA((strlen(sql_row[2]) + 1)*sizeof(char)); - strcpy(p,sql_row[2]); - s= add_str(buf1); - idb_put(mapregstr_db,(i<<24)|s,p); - }else{ - s= add_str(buf1); - v= atoi(sql_row[2]); - i = atoi(sql_row[1]); - idb_put(mapreg_db,(i<<24)|s,(void *)v); - } - } + + SqlStmt_BindColumn(stmt, 0, SQLDT_STRING, &varname[0], 32, &length, NULL); + SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL); + SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], 255, NULL, NULL); + + while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) + { + if( varname[length-1] == '$' ) { + int s = add_str(varname); + int i = index; + char* p = aStrdup(value); + idb_put(mapregstr_db, (i<<24)|s, p); + } else { + int s = add_str(varname); + int i = index; + int v = atoi(value); + idb_put(mapreg_db, (i<<24)|s, (void *)v); + } } - ShowInfo("Freeing results...\n"); - mysql_free_result(sql_res); - mapreg_dirty=0; - perfomance = (((unsigned int)time(NULL)) - perfomance); - ShowInfo("SQL Mapreg Loading Completed Under %d Seconds.\n",perfomance); + + SqlStmt_Free(stmt); + + mapreg_dirty = 0; return 0; + #endif /* TXT_ONLY */ } /*========================================== @@ -3394,56 +3386,50 @@ static int script_load_mapreg(void) *------------------------------------------*/ static int script_save_mapreg_intsub(DBKey key,void *data,va_list ap) { -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp=va_arg(ap,FILE*); int num=key.i&0x00ffffff, i=key.i>>24; char *name=str_buf+str_data[num].str; - if( name[1]!='@' ){ + +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp=va_arg(ap,FILE*); + if( name[1]!='@' ) { if(i==0) fprintf(fp,"%s\t%d\n", name, (int)data); else fprintf(fp,"%s,%d\t%d\n", name, i, (int)data); } - return 0; #else - int num=key.i&0x00ffffff, i=key.i>>24; // [zBuffer] - char *name=str_buf+str_data[num].str; if ( name[1] != '@') { - sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%d' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,(int)data,mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `%s`='%d' WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_value, (int)data, mapregsql_db_varname, name, mapregsql_db_index, i) ) + Sql_ShowDebug(mmysql_handle); } - return 0; #endif + + return 0; } + static int script_save_mapreg_strsub(DBKey key,void *data,va_list ap) { -#if defined(TXT_ONLY) || !defined(MAPREGSQL) - FILE *fp=va_arg(ap,FILE*); int num=key.i&0x00ffffff, i=key.i>>24; char *name=str_buf+str_data[num].str; - if( name[1]!='@' ){ + +#if defined(TXT_ONLY) || !defined(MAPREGSQL) + FILE *fp=va_arg(ap,FILE*); + if( name[1]!='@' ) { if(i==0) fprintf(fp,"%s\t%s\n", name, (char *)data); else fprintf(fp,"%s,%d\t%s\n", name, i, (char *)data); } - return 0; #else - char tmp_str2[512]; - int num=key.i&0x00ffffff, i=key.i>>24; - char *name=str_buf+str_data[num].str; if ( name[1] != '@') { - sprintf(tmp_sql,"UPDATE `%s` SET `%s`='%s' WHERE `%s`='%s' AND `%s`='%d'",mapregsql_db,mapregsql_db_value,jstrescapecpy(tmp_str2,(char *)data),mapregsql_db_varname,name,mapregsql_db_index,i); - if(mysql_query(&mmysql_handle, tmp_sql) ) { - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - } + char tmp_str2[2*255+1]; + Sql_EscapeStringLen(mmysql_handle, tmp_str2, (char*)data, strnlen((char*)data, 255)); + if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `%s`='%s' WHERE `%s`='%s' AND `%s`='%d'", mapregsql_db, mapregsql_db_value, tmp_str2, mapregsql_db_varname, name, mapregsql_db_index, i) ) + Sql_ShowDebug(mmysql_handle); } - return 0; #endif + + return 0; } static int script_save_mapreg(void) { @@ -3459,12 +3445,8 @@ static int script_save_mapreg(void) mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub,fp); lock_fclose(fp,mapreg_txt,&lock); #else - unsigned int perfomance = (unsigned int)time(NULL); - mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub); // [zBuffer] + mapreg_db->foreach(mapreg_db,script_save_mapreg_intsub); mapregstr_db->foreach(mapregstr_db,script_save_mapreg_strsub); - perfomance = ((unsigned int)time(NULL) - perfomance); - if(perfomance > 2) - ShowWarning("Slow Query: MapregSQL Saving @ %d second(s).\n", perfomance); #endif mapreg_dirty=0; return 0; @@ -3688,9 +3670,8 @@ int do_init_script() script_load_mapreg(); - add_timer_func_list(script_autosave_mapreg,"script_autosave_mapreg"); - add_timer_interval(gettick()+MAPREG_AUTOSAVE_INTERVAL, - script_autosave_mapreg,0,0,MAPREG_AUTOSAVE_INTERVAL); + add_timer_func_list(script_autosave_mapreg, "script_autosave_mapreg"); + add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL); return 0; } @@ -12098,6 +12079,7 @@ BUILDIN_FUNC(checkcell) // <--- [zBuffer] List of mathematics commands // [zBuffer] List of dynamic var commands ---> +//FIXME: some other functions are using this private function void setd_sub(struct script_state *st, TBL_PC *sd, char *varname, int elem, void *value, struct linkdb_node **ref) { set_reg(st, sd, add_str(varname)+(elem<<24), varname, value, ref); @@ -12131,80 +12113,78 @@ BUILDIN_FUNC(setd) BUILDIN_FUNC(query_sql) { #ifndef TXT_ONLY - char *name = NULL; - const char *query; - int num, i = 0,j, nb_rows; - struct { char * dst_var_name; char type; } row[32]; - TBL_PC *sd = (st->rid)? script_rid2sd(st) : NULL; + int i, j, nb_rows; + struct { char* dst_var_name; char type; } row[32]; + TBL_PC* sd = (st->rid) ? script_rid2sd(st) : NULL; - query = script_getstr(st,2); - strcpy(tmp_sql, query); - if(mysql_query(&mmysql_handle,tmp_sql)){ - ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle)); - ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql); - script_pushint(st,0); + const char* query = script_getstr(st,2); + if (SQL_ERROR == Sql_Query(mmysql_handle, query) ) + { + Sql_ShowDebug(mmysql_handle); + script_pushint(st, 0); return 1; } - // If some data was returned - if((sql_res = mysql_store_result(&mmysql_handle))){ - // Count the number of rows to store - nb_rows = mysql_num_fields(sql_res); + // Count the number of rows to store + nb_rows = Sql_NumColumns(mmysql_handle); + //FIXME: what sick mind would write something like this? - // Can't store more row than variable - if (nb_rows > st->end - (st->start+3)) - nb_rows = st->end - (st->start+3); + // Can't store more row than variable + if (nb_rows > st->end - (st->start+3)) + nb_rows = st->end - (st->start+3); - if (!nb_rows) - { - script_pushint(st,0); - return 0; // Nothing to store - } + if (!nb_rows) + { + script_pushint(st,0); + return 0; // Nothing to store + } - if (nb_rows > 32) - { - ShowWarning("buildin_query_sql: too many rows!\n"); - script_pushint(st,0); - return 1; - } + if (nb_rows > 32) + { + ShowWarning("buildin_query_sql: too many rows!\n"); + script_pushint(st,0); + return 1; + } - memset(row, 0, sizeof(row)); - // Verify argument types - for(j=0; j < nb_rows; j++) - { - if(!data_isreference(script_getdata(st, 3+j))){ - ShowWarning("buildin_query_sql: Parameter %d is not a variable!\n", j); - script_pushint(st,0); - return 0; - } else { - // Store type of variable (string = 0/int = 1) - num=st->stack->stack_data[st->start+3+j].u.num; - name=(char *)(str_buf+str_data[num&0x00ffffff].str); - if(name[strlen(name)-1] != '$') { - row[j].type = 1; - } - row[j].dst_var_name = name; + memset(row, 0, sizeof(row)); + // Verify argument types + for(j=0; j < nb_rows; j++) + { + if(!data_isreference(script_getdata(st, 3+j))){ + ShowWarning("buildin_query_sql: Parameter %d is not a variable!\n", j); + script_pushint(st,0); + return 0; + } else { + // Store type of variable (string = 0/int = 1) + int num = st->stack->stack_data[st->start+3+j].u.num; + char* name = str_buf + str_data[num&0x00ffffff].str; + if(name[strlen(name)-1] != '$') { + row[j].type = 1; } + row[j].dst_var_name = name; } - // Store data - while(i<128 && (sql_row = mysql_fetch_row(sql_res))){ - for(j=0; j < nb_rows; j++) - { - if (row[j].type == 1) - setd_sub(st,sd, row[j].dst_var_name, i, (void *)atoi(sql_row[j]),script_getref(st,3+j)); - else - setd_sub(st,sd, row[j].dst_var_name, i, (void *)sql_row[j],script_getref(st,3+j)); - } - i++; + } + // Store data + for (i = 0; i < 128 && SQL_SUCCESS == Sql_NextRow(mmysql_handle); i++) + { + char* data; + Sql_GetData(mmysql_handle, j, &data, NULL); + for(j = 0; j < nb_rows; j++) { + if (row[j].type == 1) + setd_sub(st,sd, row[j].dst_var_name, i, (void *)atoi(data), script_getref(st,3+j)); + else + setd_sub(st,sd, row[j].dst_var_name, i, (void *)data, script_getref(st,3+j)); } - // Free data - mysql_free_result(sql_res); } + // Free data + Sql_FreeResult(mmysql_handle); + script_pushint(st,i); #else //for TXT version, we always return -1 script_pushint(st,-1); #endif + return 0; } diff --git a/src/map/skill.c b/src/map/skill.c index fc365b7d3..df7564629 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -7,6 +7,7 @@ #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/strlib.h" +#include "../common/utils.h" #include "../common/ers.h" #include "skill.h" diff --git a/src/map/status.c b/src/map/status.c index b1e2bb1df..b5f0dbfe8 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -6,6 +6,7 @@ #include "../common/nullpo.h" #include "../common/showmsg.h" #include "../common/malloc.h" +#include "../common/utils.h" #include "pc.h" #include "map.h" diff --git a/src/plugins/Makefile b/src/plugins/Makefile deleted file mode 100644 index bac69f70f..000000000 --- a/src/plugins/Makefile +++ /dev/null @@ -1,42 +0,0 @@ - -OBJECTS = sample.dll sig.dll pid.dll gui.dll upnp.dll console.dll - -ifdef CYGWIN - PLUGINEXT = dll -else - PLUGINEXT = so -endif - -PLUGINS = $(OBJECTS:%.dll=%.$(PLUGINEXT)) -COMMON_H = ../common/plugin.h ../common/cbasetypes.h - -txt sql all: $(PLUGINS) - -%.$(PLUGINEXT): %.c - $(CC) $(CFLAGS) -shared -o ../../plugins/$@ $< - -sig.$(PLUGINEXT): sig.c - $(CC) $(CFLAGS) -shared -o ../../plugins/$@ $< \ - ../common/obj/showmsg.o ../common/obj/utils.o \ - ../common/obj/minimalloc.o - -gui.$(PLUGINEXT): ../../plugins/gui.conf -upnp.$(PLUGINEXT): ../../plugins/upnp.conf - -../../plugins/%.conf: %.txt - cp -r $< $@ - -../../plugins/gui.conf: gui.txt -../../plugins/upnp.conf: upnp.txt - -depend: - makedepend -fGNUmakefile -o.$(PLUGINEXT) -Y. -Y../common *.c $(PLUGINS:%=../../plugins/%) -clean: - rm -rf $(PLUGINS) GNUmakefile - -# DO NOT DELETE - -sample.$(PLUGINEXT): sample.c $(COMMON_H) -sig.$(PLUGINEXT): sig.c $(COMMON_H) -pid.$(PLUGINEXT): pid.c $(COMMON_H) -gui.$(PLUGINEXT): gui.c $(COMMON_H) diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in new file mode 100644 index 000000000..769771aca --- /dev/null +++ b/src/plugins/Makefile.in @@ -0,0 +1,67 @@ +@SET_MAKE@ + +PLUGINS = sample sig pid gui upnp console + +COMMON_H = ../common/plugin.h ../common/cbasetypes.h + +##################################################################### +.PHONY : all $(PLUGINS) clean help + +all: $(PLUGINS) + +sample: sample@DLLEXT@ + +sig: sig@DLLEXT@ + +pid: pid@DLLEXT@ + +gui: gui@DLLEXT@ + +upnp: upnp@DLLEXT@ + +console: console@DLLEXT@ + +clean: + rm -rf *.o + +help: + @echo "possible targets are $(PLUGINS:%='%') 'all' 'clean' 'help'" + @echo "'sample' - sample plugin" + @echo "'sig' - signal handler plugin" + @echo "'pid' - process id plugin" + @echo "'gui' - gui plugin" + @echo "'upnp' - upnp plugin" + @echo "'console' - console plugin" + @echo "'all' - builds all above targets" + @echo "'clean' - cleans builds and objects" + @echo "'help' - outputs this message" + +##################################################################### + +%@DLLEXT@: %.c + @CC@ @CFLAGS@ @CPPFLAGS@ -shared -o ../../plugins/$@ $< + +sig@DLLEXT@: sig.c + @$(MAKE) -C ../common txt + @CC@ @CFLAGS@ @CPPFLAGS@ -shared -o ../../plugins/$@ $< \ + ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o \ + ../common/obj/minimalloc.o + +gui@DLLEXT@: ../../plugins/gui.conf +upnp@DLLEXT@: ../../plugins/upnp.conf + +../../plugins/%.conf: %.txt + cp -r $< $@ + +../../plugins/gui.conf: gui.txt +../../plugins/upnp.conf: upnp.txt + +# DO NOT DELETE + +sample@DLLEXT@: sample.c $(COMMON_H) +sig@DLLEXT@: sig.c $(COMMON_H) +pid@DLLEXT@: pid.c $(COMMON_H) +gui@DLLEXT@: gui.c $(COMMON_H) +#TODO where is upnp.c? [FlavioJS] +#upnp@DLLEXT@: upnp.c $(COMMON_H) +console@DLLEXT@: console.c $(COMMON_H) diff --git a/src/tool/Makefile b/src/tool/Makefile deleted file mode 100644 index fef165ba5..000000000 --- a/src/tool/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -all: adduser convert mapcache - -adduser: - $(CC) -o ../../tools/$@ adduser.c - -convert: - $(CC) -o ../../tools/$@ convert.c - -mapcache: - $(CC) -c -o grfio.o grfio.c - $(CC) -o ../../$@ mapcache.c grfio.o -lz - -clean: - rm -rf *.o ../../tools/adduser ../../tools/convert ../../mapcache diff --git a/src/tool/Makefile.in b/src/tool/Makefile.in new file mode 100644 index 000000000..7c0d1e1ee --- /dev/null +++ b/src/tool/Makefile.in @@ -0,0 +1,28 @@ +##################################################################### +.PHONY : all adduser convert mapcache clean help + +all: adduser convert mapcache + +adduser: + @CC@ -o ../../tools/adduser@EXEEXT@ adduser.c + +convert: + @CC@ -o ../../tools/convert@EXEEXT@ convert.c + +mapcache: + @CC@ -c -o grfio.o grfio.c + @CC@ -o ../../mapcache@EXEEXT@ mapcache.c grfio.o -lz + +clean: + rm -rf *.o ../../tools/adduser@EXEEXT@ ../../tools/convert@EXEEXT@ ../../mapcache@EXEEXT@ + +help: + @echo "possible targets are 'adduser' 'convert' 'mapcache' 'all' 'clean' 'help'" + @echo "'adduser' - ???" + @echo "'convert' - ???" + @echo "'mapcache' - mapcache generator" + @echo "'all' - builds all above targets" + @echo "'clean' - cleans builds and objects" + @echo "'help' - outputs this message" + +##################################################################### diff --git a/src/txt-converter/Makefile b/src/txt-converter/Makefile deleted file mode 100644 index 419029e19..000000000 --- a/src/txt-converter/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -all sql: char-converter login-converter - -char-converter: char-converter.o ../common/obj/minicore.o \ - ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o \ - ../common/obj/mapindex.o ../common/obj/ers.o ../common/obj/utils.o \ - ../char/char.o ../char/int_pet.o ../char/int_storage.o ../char/inter.o \ - ../char/int_party.o ../char/int_guild.o \ - ../char_sql/char.o ../char_sql/int_pet.o ../char_sql/int_storage.o \ - ../char_sql/inter.o ../char_sql/int_party.o ../char_sql/int_guild.o - $(CC) -o ../../tools/$@ $^ $(LIB_S) - -login-converter: login-converter.o ../common/obj/minicore.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/ers.o ../common/obj/utils.o - $(CC) -o ../../tools/$@ $^ $(LIB_S) - -clean: - rm -f *.o ../../tools/login-converter ../../tools/char-converter GNUmakefile - -# DO NOT DELETE - -%.o: %.c - $(COMPILE.c) -DTXT_SQL_CONVERT $(OUTPUT_OPTION) $< - -char-converter.o: char-converter.c -login-converter.o: login-converter.c diff --git a/src/txt-converter/Makefile.in b/src/txt-converter/Makefile.in new file mode 100644 index 000000000..31d593743 --- /dev/null +++ b/src/txt-converter/Makefile.in @@ -0,0 +1,68 @@ +LOGIN_CONVERTER_OBJ = login-converter.o ../common/obj/minicore.o \ + ../common/obj/malloc.o ../common/obj/strlib.o ../common/obj/showmsg.o \ + ../common/obj/utils.o ../common/obj/ers.o ../common/obj/db.o \ + ../common/obj_sql/sql.o +CHAR_CONVERTER_OBJ = char-converter.o ../common/obj/minicore.o \ + ../common/obj/malloc.o ../common/obj/strlib.o ../common/obj/showmsg.o \ + ../common/obj/utils.o ../common/obj/ers.o ../common/obj/mapindex.o \ + ../common/obj_sql/sql.o \ + obj_txt/char.o obj_txt/int_pet.o obj_txt/int_storage.o obj_txt/inter.o \ + obj_txt/int_party.o obj_txt/int_guild.o \ + obj_sql/char.o obj_sql/int_pet.o obj_sql/int_storage.o \ + obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o + +HAVE_MYSQL=@HAVE_MYSQL@ +ifeq ($(HAVE_MYSQL),yes) + LOGIN_CONVERTER_DEPENDS=$(LOGIN_CONVERTER_OBJ) + CHAR_CONVERTER_DEPENDS=obj $(CHAR_CONVERTER_OBJ) +else + LOGIN_CONVERTER_DEPENDS=needs_mysql + CHAR_CONVERTER_DEPENDS=needs_mysql +endif + +##################################################################### +.PHONY : all login-converter char-converter clean help + +all: login-converter char-converter + +login-converter: $(LOGIN_CONVERTER_DEPENDS) + @CC@ @LDFLAGS@ -o ../../tools/login-converter@EXEEXT@ $(LOGIN_CONVERTER_OBJ) @LIBS@ @MYSQL_LIBS@ + +char-converter: $(CHAR_CONVERTER_DEPENDS) + @CC@ @LDFLAGS@ -o ../../tools/char-converter@EXEEXT@ $(CHAR_CONVERTER_OBJ) @LIBS@ @MYSQL_LIBS@ + +clean: + rm -rf *.o obj_txt obj_sql ../../tools/login-converter@EXEEXT@ ../../tools/char-converter@EXEEXT@ + +help: + @echo "possible targets are 'login-converter' 'char-converter' 'all' 'clean' 'help'" + @echo "'login-converter' - login server converter" + @echo "'char-converter' - char server converter" + @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: + -mkdir obj_txt + -mkdir obj_sql + + +# DO NOT DELETE + +%.o: %.c + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -DTXT_SQL_CONVERT -c $(OUTPUT_OPTION) $< + +obj_txt/%.o: ../char/%.c + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -DTXT_SQL_CONVERT -c $(OUTPUT_OPTION) $< + +obj_sql/%.o: ../char_sql/%.c + @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -DTXT_SQL_CONVERT -c $(OUTPUT_OPTION) $< + +char-converter.o: char-converter.c +login-converter.o: login-converter.c diff --git a/src/txt-converter/char-converter.c b/src/txt-converter/char-converter.c index 63c261604..8168e0ee3 100644 --- a/src/txt-converter/char-converter.c +++ b/src/txt-converter/char-converter.c @@ -7,6 +7,7 @@ #include "../common/strlib.h" #include "../common/showmsg.h" #include "../common/mapindex.h" +#include "../common/utils.h" #include "../char/char.h" #include "../char/int_storage.h" diff --git a/src/txt-converter/login-converter.c b/src/txt-converter/login-converter.c index 6c194b9d5..114ec7735 100644 --- a/src/txt-converter/login-converter.c +++ b/src/txt-converter/login-converter.c @@ -6,16 +6,12 @@ #include "../common/core.h" #include "../common/db.h" #include "../common/showmsg.h" +#include "../common/sql.h" #include <stdio.h> #include <stdlib.h> #include <string.h> -#ifdef WIN32 -#include <winsock2.h> -#endif -#include <mysql.h> - char login_account_id[256]="account_id"; char login_userid[256]="userid"; char login_user_pass[256]="user_pass"; @@ -90,8 +86,8 @@ int read_gm_account() int convert_login(void) { - MYSQL mysql_handle; - char tmpsql[1024]; + Sql* mysql_handle; + SqlStmt* stmt; int line_counter = 0; FILE *fp; int account_id, logincount, user_level, state, n, i; @@ -100,11 +96,12 @@ int convert_login(void) time_t connect_until_time; char dummy[2048]; - mysql_init(&mysql_handle); - if(!mysql_real_connect(&mysql_handle, db_server_ip, db_server_id, db_server_pw, db_server_logindb ,db_server_port, (char *)NULL, 0)) { - //pointer check - printf("%s\n",mysql_error(&mysql_handle)); - exit(1); + 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) ) + { + Sql_ShowDebug(mysql_handle); + Sql_Free(mysql_handle); + exit(1); } ShowStatus("Connect: Success!\n"); @@ -133,21 +130,27 @@ int convert_login(void) user_level = isGM(account_id); ShowInfo("Converting user (id: %d, name: %s, gm level: %d)\n", account_id, userid, user_level); - sprintf(tmpsql, + + 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`, `connect_until`, `last_ip`, `memo`, `ban_until`, `state`) " "VALUES " - "(%d, '%s', '%s', '%s', '%c', %d, '%s', %d, '%s', %u, '%s', '%s', %u, %d)", - account_id , userid, pass, lastlogin, sex, logincount, email, user_level, error_message, (uint32)connect_until_time, last_ip, memo, (uint32)ban_until_time, state); - if(mysql_query(&mysql_handle, tmpsql) ) { - ShowError("DB server Error - %s\n", mysql_error(&mysql_handle) ); - ShowError("Query: %s\n", tmpsql); + "(%d, ?, ?, '%s', '%c', %d, '%s', %d, '%s', %u, '%s', '%s', %u, %d)", + account_id, lastlogin, sex, logincount, email, user_level, error_message, (uint32)connect_until_time, last_ip, memo, (uint32)ban_until_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 } fclose(fp); + Sql_Free(mysql_handle); ShowStatus("Convert end...\n"); diff --git a/vcproj-6/char-server_sql.dsp b/vcproj-6/char-server_sql.dsp index aa85a3344..f84332a7b 100644 --- a/vcproj-6/char-server_sql.dsp +++ b/vcproj-6/char-server_sql.dsp @@ -147,6 +147,14 @@ 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
@@ -233,14 +241,6 @@ SOURCE=..\src\char_sql\inter.c SOURCE=..\src\char_sql\inter.h
# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\itemdb.c
-# End Source File
-# Begin Source File
-
-SOURCE=..\src\char_sql\itemdb.h
-# End Source File
# End Group
# End Target
# End Project
diff --git a/vcproj-6/login-server_sql.dsp b/vcproj-6/login-server_sql.dsp index 17bcff167..07f853727 100644 --- a/vcproj-6/login-server_sql.dsp +++ b/vcproj-6/login-server_sql.dsp @@ -155,6 +155,14 @@ 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
diff --git a/vcproj-6/map-server_sql.dsp b/vcproj-6/map-server_sql.dsp index f41048829..f18eda8c6 100644 --- a/vcproj-6/map-server_sql.dsp +++ b/vcproj-6/map-server_sql.dsp @@ -155,6 +155,14 @@ 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
diff --git a/vcproj-7.1/char-server_sql.vcproj b/vcproj-7.1/char-server_sql.vcproj index 09316641b..ec46bb71c 100644 --- a/vcproj-7.1/char-server_sql.vcproj +++ b/vcproj-7.1/char-server_sql.vcproj @@ -185,12 +185,6 @@ <File RelativePath="..\src\char_sql\inter.h"> </File> - <File - RelativePath="..\src\char_sql\itemdb.c"> - </File> - <File - RelativePath="..\src\char_sql\itemdb.h"> - </File> </Filter> <Filter Name="common" @@ -265,6 +259,12 @@ RelativePath="..\src\common\socket.h"> </File> <File + RelativePath="..\src\common\sql.c"> + </File> + <File + RelativePath="..\src\common\sql.h"> + </File> + <File RelativePath="..\src\common\strlib.c"> </File> <File diff --git a/vcproj-7.1/login-server_sql.vcproj b/vcproj-7.1/login-server_sql.vcproj index 30313087d..37028adc5 100644 --- a/vcproj-7.1/login-server_sql.vcproj +++ b/vcproj-7.1/login-server_sql.vcproj @@ -224,6 +224,12 @@ RelativePath="..\src\common\socket.h"> </File> <File + RelativePath="..\src\common\sql.c"> + </File> + <File + RelativePath="..\src\common\sql.h"> + </File> + <File RelativePath="..\src\common\strlib.c"> </File> <File diff --git a/vcproj-7.1/map-server_sql.vcproj b/vcproj-7.1/map-server_sql.vcproj index 1c9649547..ff3662304 100644 --- a/vcproj-7.1/map-server_sql.vcproj +++ b/vcproj-7.1/map-server_sql.vcproj @@ -395,6 +395,12 @@ RelativePath="..\src\common\socket.h"> </File> <File + RelativePath="..\src\common\sql.c"> + </File> + <File + RelativePath="..\src\common\sql.h"> + </File> + <File RelativePath="..\src\common\strlib.c"> </File> <File diff --git a/vcproj-8/char-server_sql.vcproj b/vcproj-8/char-server_sql.vcproj index 8d704bbdf..0427e7c27 100644 --- a/vcproj-8/char-server_sql.vcproj +++ b/vcproj-8/char-server_sql.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" - Version="8,00" + Version="8.00" Name="char-server_sql" ProjectGUID="{D356871D-58E1-450B-967A-E4E9646175AF}" RootNamespace="char-server_sql" @@ -298,6 +298,14 @@ > </File> <File + RelativePath="..\src\common\sql.c" + > + </File> + <File + RelativePath="..\src\common\sql.h" + > + </File> + <File RelativePath="..\src\common\strlib.c" > </File> @@ -385,14 +393,6 @@ RelativePath="..\src\char_sql\inter.h" > </File> - <File - RelativePath="..\src\char_sql\itemdb.c" - > - </File> - <File - RelativePath="..\src\char_sql\itemdb.h" - > - </File> </Filter> </Files> <Globals> diff --git a/vcproj-8/char-server_txt.vcproj b/vcproj-8/char-server_txt.vcproj index fd8a87dfe..531c5519e 100644 --- a/vcproj-8/char-server_txt.vcproj +++ b/vcproj-8/char-server_txt.vcproj @@ -224,6 +224,10 @@ > </File> <File + RelativePath="..\src\char\int_homun.h" + > + </File> + <File RelativePath="..\src\char\int_party.c" > </File> diff --git a/vcproj-8/login-server_sql.vcproj b/vcproj-8/login-server_sql.vcproj index c7f4bf252..9a128df80 100644 --- a/vcproj-8/login-server_sql.vcproj +++ b/vcproj-8/login-server_sql.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" - Version="8,00" + Version="8.00" Name="login-server_sql" ProjectGUID="{D356871D-58E1-450B-967A-E5E9646175AF}" RootNamespace="login-server_sql" @@ -312,6 +312,14 @@ > </File> <File + RelativePath="..\src\common\sql.c" + > + </File> + <File + RelativePath="..\src\common\sql.h" + > + </File> + <File RelativePath="..\src\common\strlib.c" > </File> diff --git a/vcproj-8/map-server_sql.vcproj b/vcproj-8/map-server_sql.vcproj index bdad0a326..913422ea2 100644 --- a/vcproj-8/map-server_sql.vcproj +++ b/vcproj-8/map-server_sql.vcproj @@ -305,6 +305,14 @@ > </File> <File + RelativePath="..\src\common\sql.c" + > + </File> + <File + RelativePath="..\src\common\sql.h" + > + </File> + <File RelativePath="..\src\common\strlib.c" > </File> diff --git a/vcproj-8/txt-converter-char.vcproj b/vcproj-8/txt-converter-char.vcproj index e53bed304..7e2b1bd45 100644 --- a/vcproj-8/txt-converter-char.vcproj +++ b/vcproj-8/txt-converter-char.vcproj @@ -204,24 +204,6 @@ <File RelativePath="..\src\char\char.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\char.h" @@ -230,24 +212,6 @@ <File RelativePath="..\src\char\int_guild.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\int_guild.h" @@ -256,24 +220,6 @@ <File RelativePath="..\src\char\int_party.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\int_party.h" @@ -282,24 +228,6 @@ <File RelativePath="..\src\char\int_pet.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\int_pet.h" @@ -308,24 +236,6 @@ <File RelativePath="..\src\char\int_storage.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\int_storage.h" @@ -334,24 +244,6 @@ <File RelativePath="..\src\char\inter.c" > - <FileConfiguration - Name="Debug|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - ObjectFile="$(IntDir)\$(InputName)1.obj" - XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" - /> - </FileConfiguration> </File> <File RelativePath="..\src\char\inter.h" @@ -402,6 +294,14 @@ > </File> <File + RelativePath="..\src\common\sql.c" + > + </File> + <File + RelativePath="..\src\common\sql.h" + > + </File> + <File RelativePath="..\src\common\strlib.c" > </File> diff --git a/vcproj-8/txt-converter-login.vcproj b/vcproj-8/txt-converter-login.vcproj index 2997e471b..3036b0f3f 100644 --- a/vcproj-8/txt-converter-login.vcproj +++ b/vcproj-8/txt-converter-login.vcproj @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject ProjectType="Visual C++" - Version="8,00" + Version="8.00" Name="txt-converter-login" ProjectGUID="{D356871D-58E1-450B-967A-E9E9646175AF}" RootNamespace="txt-converter-login" @@ -97,6 +97,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -191,6 +194,9 @@ Name="VCAppVerifierTool" /> <Tool + Name="VCWebDeploymentTool" + /> + <Tool Name="VCPostBuildEventTool" /> </Configuration> @@ -242,11 +248,19 @@ > </File> <File - RelativePath="..\src\common\utils.c" + RelativePath="..\src\common\sql.c" + > + </File> + <File + RelativePath="..\src\common\sql.h" + > + </File> + <File + RelativePath="..\src\common\strlib.c" > </File> <File - RelativePath="..\src\common\utils.h" + RelativePath="..\src\common\strlib.h" > </File> </Filter> |