forked from metin2/server
Compare commits
10 Commits
nightly
...
config/env
Author | SHA1 | Date | |
---|---|---|---|
e642a6db52 | |||
04fdc78ea4 | |||
2b9651febc | |||
8f9e9dc602 | |||
170be95dc5 | |||
6d65fae7e4 | |||
8ed1e7879e | |||
65a81ec4a1 | |||
ae708d9315 | |||
21e028f186 |
@ -15,4 +15,7 @@ gamefiles/data/quest/pre_qc/
|
||||
gamefiles/data/quest/qc
|
||||
|
||||
# Test folder
|
||||
test/
|
||||
test/
|
||||
|
||||
# Built files
|
||||
build/
|
15
Dockerfile
15
Dockerfile
@ -9,7 +9,7 @@ RUN echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https:
|
||||
# Update the system and install various dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y git cmake ninja-build build-essential tar curl zip unzip pkg-config autoconf python3 \
|
||||
libdevil-dev libncurses5-dev libbsd-dev
|
||||
libdevil-dev libncurses5-dev libbsd-dev
|
||||
|
||||
# Arm specific
|
||||
ENV VCPKG_FORCE_SYSTEM_BINARIES=1
|
||||
@ -17,7 +17,7 @@ ENV VCPKG_FORCE_SYSTEM_BINARIES=1
|
||||
# Install vcpkg and the required libraries
|
||||
RUN git clone https://github.com/Microsoft/vcpkg.git
|
||||
RUN bash ./vcpkg/bootstrap-vcpkg.sh
|
||||
RUN ./vcpkg/vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog
|
||||
RUN ./vcpkg/vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog argon2
|
||||
|
||||
COPY . .
|
||||
|
||||
@ -29,7 +29,7 @@ RUN cd build && make -j $(nproc)
|
||||
FROM ubuntu:22.04 as app
|
||||
WORKDIR /app
|
||||
|
||||
RUN apt-get update && apt-get install -y python2 libdevil-dev libbsd-dev && apt-get clean
|
||||
RUN apt-get update && apt-get install -y gettext python2 libdevil-dev libbsd-dev && apt-get clean
|
||||
|
||||
# Copy the binaries from the build stage
|
||||
COPY --from=build /app/build/src/db/db /bin/db
|
||||
@ -39,6 +39,9 @@ COPY --from=build /app/build/src/quest/qc /bin/qc
|
||||
# Copy the game files
|
||||
COPY ./gamefiles/ .
|
||||
|
||||
# Copy the auxiliary files
|
||||
COPY ./docker/ .
|
||||
|
||||
# Compile the quests
|
||||
RUN cd /app/data/quest && python2 make.py
|
||||
|
||||
@ -48,3 +51,9 @@ RUN ln -s ./conf/item_names_en.txt item_names.txt
|
||||
RUN ln -s ./conf/item_proto.txt item_proto.txt
|
||||
RUN ln -s ./conf/mob_names_en.txt mob_names.txt
|
||||
RUN ln -s ./conf/mob_proto.txt mob_proto.txt
|
||||
|
||||
# Set up default environment variables
|
||||
ENV PUBLIC_BIND_IP 0.0.0.0
|
||||
ENV INTERNAL_BIND_IP 0.0.0.0
|
||||
|
||||
ENTRYPOINT ["/usr/bin/bash", "docker-entrypoint.sh"]
|
||||
|
@ -35,11 +35,11 @@ Also install DevIL (1.7.8) and the BSD compatibility library:
|
||||
apt-get install -y libdevil-dev libbsd-dev
|
||||
```
|
||||
|
||||
Install `vcpkg` according to the [lastest instructions](https://vcpkg.io/en/getting-started.html).
|
||||
Install `vcpkg` according to the [latest instructions](https://vcpkg.io/en/getting-started.html).
|
||||
|
||||
Build and install the required libraries:
|
||||
```shell
|
||||
vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog
|
||||
vcpkg install boost-system cryptopp effolkronium-random libmysql libevent lzo fmt spdlog argon2
|
||||
```
|
||||
|
||||
Then, it's time to build your binaries. Your commands should look along the lines of:
|
||||
@ -79,8 +79,9 @@ goodies you wish. Also, a lot of time.
|
||||
- Removed unused functionalities (time bombs, activation servers, other Korean stuff)
|
||||
- Switched to the [effolkronium/random PRNG](https://github.com/effolkronium/random) instead of the standard C functions.
|
||||
- Refactored macros to modern C++ functions.
|
||||
- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `CONFIG` file. (Might need further work)
|
||||
- Network settings are manually configurable through the `PUBLIC_IP`, `PUBLIC_BIND_IP`, `INTERNAL_IP`, `INTERNAL_BIND_IP` settings in the `game.conf` file. (Might need further work)
|
||||
- Refactored logging to use [spdlog](https://github.com/gabime/spdlog) for more consistent function calls.
|
||||
- Refactored login code to use Argon2ID.
|
||||
|
||||
## 4. Bugfixes
|
||||
**WARNING: This project is based on the "kraizy" leak. That was over 10 years ago.
|
||||
@ -101,7 +102,7 @@ This is a very serious security risk and one of the reasons this project is stil
|
||||
- Fixed buffer overruns and integer overflows in SQL queries.
|
||||
|
||||
## 5. Further plans
|
||||
- Migrate `conf.txt` and `CONFIG` to a modern dotenv-like format, which would enable pretty nice Docker images.
|
||||
- Migrate `db.conf` and `game.conf` to a modern dotenv-like format, which would enable pretty nice Docker images.
|
||||
- Add a health check to the Docker image.
|
||||
- Use the [fmt](https://fmt.dev/latest/index.html) library for safe and modern string formatting.
|
||||
- Handle kernel signals (SIGTERM, SIGHUP etc.) for gracefully shutting down the game server.
|
||||
|
18
docker/conf/db.conf.tmpl
Normal file
18
docker/conf/db.conf.tmpl
Normal file
@ -0,0 +1,18 @@
|
||||
WELCOME_MSG = "DB Server has been started"
|
||||
|
||||
SQL_ACCOUNT = "${MYSQL_HOST} ${MYSQL_DB_ACCOUNT} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
|
||||
SQL_COMMON = "${MYSQL_HOST} ${MYSQL_DB_COMMON} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
|
||||
SQL_PLAYER = "${MYSQL_HOST} ${MYSQL_DB_PLAYER} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_PORT}"
|
||||
|
||||
TABLE_POSTFIX = ""
|
||||
|
||||
BIND_PORT = ${DB_PORT}
|
||||
DB_SLEEP_MSEC = 10
|
||||
CLIENT_HEART_FPS = 10
|
||||
HASH_PLAYER_LIFE_SEC = 600
|
||||
BACKUP_LIMIT_SEC = 3600
|
||||
PLAYER_ID_START = 100
|
||||
PLAYER_DELETE_LEVEL_LIMIT = 70
|
||||
|
||||
ITEM_ID_RANGE = 10000001 20000000
|
||||
TEST_SERVER = ${TEST_SERVER}
|
41
docker/conf/game.conf.tmpl
Normal file
41
docker/conf/game.conf.tmpl
Normal file
@ -0,0 +1,41 @@
|
||||
HOSTNAME: ${GAME_HOSTNAME}
|
||||
CHANNEL: ${GAME_CHANNEL}
|
||||
|
||||
PUBLIC_IP: ${PUBLIC_IP}
|
||||
PUBLIC_BIND_IP: ${PUBLIC_BIND_IP}
|
||||
INTERNAL_IP: ${INTERNAL_IP}
|
||||
INTERNAL_BIND_IP: ${INTERNAL_BIND_IP}
|
||||
PORT: ${GAME_PORT}
|
||||
P2P_PORT: ${GAME_P2P_PORT}
|
||||
|
||||
DB_ADDR: ${DB_ADDR}
|
||||
DB_PORT: ${DB_PORT}
|
||||
|
||||
COMMON_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_COMMON} ${MYSQL_PORT}
|
||||
LOG_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_LOG} ${MYSQL_PORT}
|
||||
PLAYER_SQL: ${MYSQL_HOST} ${MYSQL_USER} ${MYSQL_PASSWORD} ${MYSQL_DB_PLAYER} ${MYSQL_PORT}
|
||||
TABLE_POSTFIX:
|
||||
|
||||
AUTH_SERVER: ${GAME_AUTH_SERVER}
|
||||
MARK_SERVER: ${GAME_MARK_SERVER}
|
||||
|
||||
MAP_ALLOW: ${GAME_MAP_ALLOW}
|
||||
MAX_LEVEL: ${GAME_MAX_LEVEL}
|
||||
PK_PROTECT_LEVEL: 15
|
||||
SPAM_BLOCK_MAX_LEVEL: 90
|
||||
GOLD_DROP_LIMIT_TIME: 10
|
||||
MALL_URL: ${GAME_MALL_URL}
|
||||
|
||||
CHECK_MULTIHACK: 0
|
||||
SPEEDHACK_LIMIT_COUNT: 300
|
||||
SPEEDHACK_LIMIT_BONUS: 80
|
||||
|
||||
ADMINPAGE_IP: 127.0.0.1
|
||||
ADMINPAGE_PASSWORD: metin2adminpass
|
||||
|
||||
PASSES_PER_SEC: 25
|
||||
SAVE_EVENT_SECOND_CYCLE: 180
|
||||
PING_EVENT_SECOND_CYCLE: 180
|
||||
VIEW_RANGE: 8000
|
||||
|
||||
TEST_SERVER: ${TEST_SERVER}
|
9
docker/docker-entrypoint.sh
Normal file
9
docker/docker-entrypoint.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
# docker-entrypoint.sh
|
||||
|
||||
# Generate configuration files based on environment variables
|
||||
envsubst <"/app/conf/db.conf.tmpl" >"/app/db.conf"
|
||||
envsubst <"/app/conf/game.conf.tmpl" >"/app/game.conf"
|
||||
|
||||
# Run the standard container command.
|
||||
exec "$@"
|
@ -46,13 +46,13 @@ Mysql-Funktion der neuesten Generation.
|
||||
--]]
|
||||
mysql_query = function(query)
|
||||
if not pre then
|
||||
local rt = io.open('CONFIG','r'):read('*all')
|
||||
local rt = io.open('game.conf','r'):read('*all')
|
||||
pre,_= string.gsub(rt,'.+PLAYER_SQL:%s(%S+)%s(%S+)%s(%S+)%s(%S+).+','-h%1 -u%2 -p%3 -D%4')
|
||||
end
|
||||
math.randomseed(os.time())
|
||||
local fi,t,out = 'mysql_data_'..math.random(10^9)+math.random(2^4,2^10),{},{}
|
||||
--os.execute('mysql '..pre..' --e='..string.format('%q',query)..' > '..fi) -- f<>r MySQL51
|
||||
os.execute('mysql '..pre..' -e'..string.format('%q',query)..' > '..fi) -- f<>r MySQL55
|
||||
--os.execute('mysql '..pre..' --e='..string.format('%q',query)..' > '..fi) -- f<>r MySQL51
|
||||
os.execute('mysql '..pre..' -e'..string.format('%q',query)..' > '..fi) -- f<>r MySQL55
|
||||
for av in io.open(fi,'r'):lines() do table.insert(t,split(av,'\t')) end; os.remove(fi);
|
||||
for i = 2, table.getn(t) do table.foreach(t[i],function(a,b)
|
||||
out[i-1] = out[i-1] or {}
|
||||
@ -100,7 +100,7 @@ function mysql_query_old(query,user,pass,db,ip)
|
||||
os.remove(path)
|
||||
if type(q.l[1]) ~= "table" then
|
||||
return "ERROR"
|
||||
--error("Fehler bei der MySQL Verbindung oder bei der R<>ckgabe! Abbruch!")
|
||||
--error("Fehler bei der MySQL Verbindung oder bei der R<>ckgabe! Abbruch!")
|
||||
end
|
||||
local ix = 0
|
||||
table.foreachi(q.l,function(i,l)
|
||||
@ -115,7 +115,7 @@ function mysql_query_old(query,user,pass,db,ip)
|
||||
end) end
|
||||
end)
|
||||
-- ENDE der eigentlichen MySQL-Funktion
|
||||
-- START Zusatz: Hanashi-Kompatibilit<69>t & Fehlerbehandlung
|
||||
-- START Zusatz: Hanashi-Kompatibilit<69>t & Fehlerbehandlung
|
||||
q.out.__data = q.l[1]
|
||||
setmetatable(q.out, { __index = function(a,b)
|
||||
if type(b) == "number" then
|
||||
@ -132,7 +132,7 @@ end
|
||||
@name define
|
||||
@author Mijago
|
||||
@descr
|
||||
Gibt die M<>glichkeit, globale Variablen zu definieren. Es k<>nnen auch Funktionen genutzt werden! Diese werden dann AUSGEF<45>HRT zur<75>ckgegeben!
|
||||
Gibt die M<>glichkeit, globale Variablen zu definieren. Es k<>nnen auch Funktionen genutzt werden! Diese werden dann AUSGEF<45>HRT zur<75>ckgegeben!
|
||||
--]]
|
||||
_G.__data = {}
|
||||
local meta = getmetatable(_G) or {}
|
||||
@ -155,7 +155,7 @@ end
|
||||
@name duration
|
||||
@author Mijago
|
||||
@descr
|
||||
Gibt die verbleibende Zeit als String zur<75>ck.
|
||||
Gibt die verbleibende Zeit als String zur<75>ck.
|
||||
--]]
|
||||
function duration(ipe)
|
||||
local ipe,dat= ipe or 0,''
|
||||
@ -183,7 +183,7 @@ end
|
||||
@name is_number
|
||||
@author Mijago
|
||||
@descr
|
||||
Pr<EFBFBD>ft, ob eine Variable eine Zahl ist.
|
||||
Pr<EFBFBD>ft, ob eine Variable eine Zahl ist.
|
||||
--]]
|
||||
function is_number(var)
|
||||
return (type(var) == "number")
|
||||
@ -194,7 +194,7 @@ end
|
||||
@name is_string
|
||||
@author Mijago
|
||||
@descr
|
||||
Pr<EFBFBD>ft, ob eine Variable ein String ist.
|
||||
Pr<EFBFBD>ft, ob eine Variable ein String ist.
|
||||
--]]
|
||||
function is_string(var)
|
||||
return (type(var) == "string")
|
||||
@ -205,7 +205,7 @@ end
|
||||
@name is_table
|
||||
@author Mijago
|
||||
@descr
|
||||
Pr<EFBFBD>ft, ob eine Variable eine Tabelle ist.
|
||||
Pr<EFBFBD>ft, ob eine Variable eine Tabelle ist.
|
||||
--]]
|
||||
function is_table(var)
|
||||
return (type(var) == "table")
|
||||
@ -216,7 +216,7 @@ end
|
||||
@name in_table
|
||||
@author Mijago
|
||||
@descr
|
||||
Pr<EFBFBD>ft, ob eine Variablei in einer Tabelle ist.
|
||||
Pr<EFBFBD>ft, ob eine Variablei in einer Tabelle ist.
|
||||
Aufruf: in_table(var,table)
|
||||
--]]
|
||||
function in_table ( e, t )
|
||||
@ -292,7 +292,7 @@ end
|
||||
@name math.minmax
|
||||
@author Mijago
|
||||
@descr
|
||||
Erm<EFBFBD>glicht die Angabe von min und max auf einmal
|
||||
Erm<EFBFBD>glicht die Angabe von min und max auf einmal
|
||||
--]]
|
||||
math.minmax = function(min,num,max)
|
||||
return math.min(math.max(num,min),max)
|
||||
@ -304,8 +304,8 @@ end
|
||||
@name n_input
|
||||
@author Mijago
|
||||
@descr
|
||||
F<EFBFBD>r Inputs nur f<>r Zahlen.
|
||||
Die Zahl ist IMMER positiv. Wenn sie nicht g<>ltig ist, ist sie 0.
|
||||
F<EFBFBD>r Inputs nur f<>r Zahlen.
|
||||
Die Zahl ist IMMER positiv. Wenn sie nicht g<>ltig ist, ist sie 0.
|
||||
--]]
|
||||
function n_input()
|
||||
return math.abs(tonumber(input()) or 0)
|
||||
@ -316,7 +316,7 @@ end
|
||||
@name long_input
|
||||
@author Mijago
|
||||
@descr
|
||||
Erm<EFBFBD>glicht es, l<>ngere Inputs zu nutzen.
|
||||
Erm<EFBFBD>glicht es, l<>ngere Inputs zu nutzen.
|
||||
--]]
|
||||
function long_input()
|
||||
local str,t = "",input()
|
||||
@ -358,7 +358,7 @@ function select2(tab,...)
|
||||
outputstr=outputstr..'sel = select("'..l..'"'
|
||||
elseif outputcount == max and tablen > outputcount+incit then
|
||||
if tablen ~= outputcount+incit+1 then
|
||||
outputstr=outputstr..',"'..l..'","N<>chste Seite") + '..incit..' '
|
||||
outputstr=outputstr..',"'..l..'","N<>chste Seite") + '..incit..' '
|
||||
if nextc > 0 then
|
||||
outputstr = outputstr..'end '
|
||||
end
|
||||
@ -392,7 +392,7 @@ end
|
||||
@descr
|
||||
Wie Select2:
|
||||
Eine Tabelle oder eine Stringliste wird auf Seiten aufgeteilt.
|
||||
Weiter, Zur<75>ck und Abbrechen (-1) Buttons.
|
||||
Weiter, Zur<75>ck und Abbrechen (-1) Buttons.
|
||||
--]]
|
||||
function select3(...)
|
||||
arg.n = nil
|
||||
@ -438,7 +438,7 @@ function select3(...)
|
||||
pe[i] = copy_tab(px[i])
|
||||
local next,back,exit = 0,0,0
|
||||
if i < table.getn(pe) and table.getn(pe) ~=1 then table.insert(pe[i],table.getn(pe[i])+1,'Weiter zu Seite '..(i+1)); next = table.getn(pe[i]) end
|
||||
if i > 1 then table.insert(pe[i],table.getn(pe[i])+1,'Zur<EFBFBD>ck zu Seite '..(i-1)); back = table.getn(pe[i]) end
|
||||
if i > 1 then table.insert(pe[i],table.getn(pe[i])+1,'Zur<EFBFBD>ck zu Seite '..(i-1)); back = table.getn(pe[i]) end
|
||||
table.insert(pe[i],table.getn(pe[i])+1,'Abbruch'); exit = table.getn(pe[i])
|
||||
if table.getn(pe) > 1 then
|
||||
say('Seite '..i..' von '..table.getn(pe))
|
||||
@ -564,7 +564,7 @@ zt.s_ms = function(s)
|
||||
@name Autoumbruch in Say
|
||||
@author Mijago
|
||||
@descr
|
||||
F<EFBFBD>gt die Funktion say2 an.
|
||||
F<EFBFBD>gt die Funktion say2 an.
|
||||
Mit ihr werden Texte automatisch umgebrochen.
|
||||
--]]
|
||||
function say2(str,dx)
|
||||
@ -616,13 +616,14 @@ end
|
||||
@author Mijago; Idee von Benhero
|
||||
@needs mysql_query
|
||||
@descr
|
||||
Funktion zum <20>ndern des Nutzerpasswortes.
|
||||
Funktion zum <20>ndern des Nutzerpasswortes.
|
||||
Angabe des Accounts kann weggelassen werden, als Accountname oder als Account ID angegeben werden.
|
||||
--]]
|
||||
account = account or {}
|
||||
function account.set_pw(pw,ac)
|
||||
if pw == nil then error("Fehler... Passwort muss gesetzt werden!") end
|
||||
local ac = ac or pc.get_account_id()
|
||||
-- This is weird behaviour and might need to be changed if ever used.
|
||||
if type(ac) == "string" then
|
||||
mysql_query("UPDATE player.player,account.account SET account.password = password("..string.format('%q',pw)..") WHERE account.id = player.account_id and player.name = '"..ac.."' LIMIT 1")
|
||||
elseif type(ac) == "number" then
|
||||
@ -635,7 +636,7 @@ end
|
||||
@name pc.check_inventory_place
|
||||
@author Mijago
|
||||
@descr
|
||||
Checkt auf Freie Inventarpl<70>tze f<>r Items der gr<67><72>e X (H<>he).
|
||||
Checkt auf Freie Inventarpl<70>tze f<>r Items der gr<67><72>e X (H<>he).
|
||||
--]]
|
||||
function pc.check_inventory_place(size)
|
||||
if size <= 0 or size > 3 then
|
||||
@ -663,7 +664,7 @@ end
|
||||
@name do_for_other
|
||||
@author Mijago
|
||||
@descr
|
||||
F<EFBFBD>hrt einen String als Luabefehle bei einem anderem User aus.
|
||||
F<EFBFBD>hrt einen String als Luabefehle bei einem anderem User aus.
|
||||
--]]
|
||||
function do_for_other(name,ding)
|
||||
local t = pc.select(find_pc_by_name(name))
|
||||
@ -678,7 +679,7 @@ end
|
||||
@descr
|
||||
Setzt die Questflag eines anderen Spielers.
|
||||
--]]
|
||||
function local_pc_setqf(name, qf,wert) -- F<>r die aktuelle Quest
|
||||
function local_pc_setqf(name, qf,wert) -- F<>r die aktuelle Quest
|
||||
local target = find_pc_by_name(name)
|
||||
local t = pc.select(target)
|
||||
pc.setqf(qf,wert)
|
||||
@ -753,7 +754,7 @@ end
|
||||
@name download
|
||||
@author Mijago
|
||||
@descr
|
||||
L<EFBFBD>dt eine Datei in den Data-Ordner.
|
||||
L<EFBFBD>dt eine Datei in den Data-Ordner.
|
||||
--]]
|
||||
function download(url) os.execute("cd data && fetch "..url.." && cd ..") end
|
||||
|
||||
@ -762,7 +763,7 @@ function download(url) os.execute("cd data && fetch "..url.." && cd ..") end
|
||||
@name dot
|
||||
@author Mijago
|
||||
@descr
|
||||
F<EFBFBD>hrt alles Zwischen $ und $ im String aus.
|
||||
F<EFBFBD>hrt alles Zwischen $ und $ im String aus.
|
||||
--]]
|
||||
function dot(x)
|
||||
return string.gsub(x, "%$(.-)%$", function (s) return loadstring(s)() end)
|
||||
@ -773,7 +774,7 @@ end
|
||||
@name dostr
|
||||
@author Mijago
|
||||
@descr
|
||||
F<EFBFBD>hrt einen String als Lua-Befehl aus.
|
||||
F<EFBFBD>hrt einen String als Lua-Befehl aus.
|
||||
--]]
|
||||
function dostr(str)
|
||||
assert(loadstring(str))()
|
||||
@ -785,7 +786,7 @@ end
|
||||
@author Mijago
|
||||
@needs mysql_query
|
||||
@descr
|
||||
Versetzt alle Accounts (au<61>er GM-Accounts) in einen "Wartungsmodus" und wieder zur<75>ck.
|
||||
Versetzt alle Accounts (au<61>er GM-Accounts) in einen "Wartungsmodus" und wieder zur<75>ck.
|
||||
--]]
|
||||
function wartungsmodus(v)
|
||||
if v == 1 or v == true then
|
||||
@ -815,7 +816,7 @@ end
|
||||
@name INI-Parser
|
||||
@author Mijago
|
||||
@descr
|
||||
Ein NEUER Parser f<>r INI-Dateien.
|
||||
Ein NEUER Parser f<>r INI-Dateien.
|
||||
--]]
|
||||
ini = {
|
||||
open = function(path)
|
||||
@ -840,7 +841,7 @@ ini = {
|
||||
else
|
||||
r = r.."\n["..section.."]\n"..key.."="..value
|
||||
end
|
||||
-- <20>berfl<66>ssige leerzeichen l<>schen
|
||||
-- <20>berfl<66>ssige leerzeichen l<>schen
|
||||
r=string.gsub(string.gsub(string.gsub(r,"^(\n)",""),"(\n)$",""),"\n\n","\n")
|
||||
local d = io.open(self.path,"w")
|
||||
d:write(r)
|
||||
@ -895,7 +896,7 @@ ini = {
|
||||
@needs split
|
||||
@descr
|
||||
-- OUTDATED --
|
||||
Ein Parser f<>r Ini-Dateien.
|
||||
Ein Parser f<>r Ini-Dateien.
|
||||
Besitzt eine Eigene Beschreibung der einzelnen Funktionen im Code.
|
||||
--]]
|
||||
do
|
||||
@ -906,9 +907,9 @@ do
|
||||
-- var:write_int(sub,name,wert)
|
||||
-- var:write_bool(sub,name,boolean)
|
||||
-- var:clear()
|
||||
-- var:read_str(sub,name,norm) -- Gibt einen String zur<75>ck. -|
|
||||
-- var:read_int(sub,name,norm) -- Gibt eine Zahl zur<75>ck -| norm wird zur<75>ckgegeben, wenn sub[name] nicht existiert.
|
||||
-- var:read_bool(sub,name,norm) -- Gibt true / False zur<75>ck -|
|
||||
-- var:read_str(sub,name,norm) -- Gibt einen String zur<75>ck. -|
|
||||
-- var:read_int(sub,name,norm) -- Gibt eine Zahl zur<75>ck -| norm wird zur<75>ckgegeben, wenn sub[name] nicht existiert.
|
||||
-- var:read_bool(sub,name,norm) -- Gibt true / False zur<75>ck -|
|
||||
-- var:delete_key(sub,nm)
|
||||
-- var:delete_section(sub)
|
||||
local ini_f = {}
|
||||
@ -997,7 +998,7 @@ do
|
||||
if self.sub[sub] == nil then return norm end
|
||||
if self.sub[sub][nm] == nil then return norm else return tonumber(self.sub[sub][nm]) end
|
||||
end
|
||||
function ini_f:read_bool(sub,nm,norm) -- Norm wird zur<75>ckgegeben, wenn der Key nm nicht existiert
|
||||
function ini_f:read_bool(sub,nm,norm) -- Norm wird zur<75>ckgegeben, wenn der Key nm nicht existiert
|
||||
if sub == '' or nm == '' or sub == nil or nm == nil then return end
|
||||
self:parse()
|
||||
if self.sub[sub] == nil then return norm end
|
||||
@ -1032,7 +1033,7 @@ end
|
||||
Wie die alten col-Befehle, sendet aber selbst.
|
||||
Also kein say(col.red('bla'))
|
||||
sondern
|
||||
csay.red('bla') reicht v<>llig aus.
|
||||
csay.red('bla') reicht v<>llig aus.
|
||||
--]]
|
||||
csay = setmetatable({__d = {
|
||||
["aliceblue"] = {240, 248, 255}, ["antiquewhite"] = {250, 235, 215}, ["aqua"] = {0, 255, 255}, ["aquamarine"] = {127, 255, 212},
|
||||
@ -1082,7 +1083,7 @@ csay = setmetatable({__d = {
|
||||
@name Farbcodes
|
||||
@author Mijago
|
||||
@descr
|
||||
Farbcodes f<>r Say
|
||||
Farbcodes f<>r Say
|
||||
--]]
|
||||
col = col or {}
|
||||
col.list= {
|
||||
|
@ -126,9 +126,9 @@ void emptybeat(LPHEART heart, int pulse)
|
||||
//
|
||||
int Start()
|
||||
{
|
||||
if (!CConfig::instance().LoadFile("conf.txt"))
|
||||
if (!CConfig::instance().LoadFile("db.conf"))
|
||||
{
|
||||
SPDLOG_ERROR("Loading conf.txt failed.");
|
||||
SPDLOG_ERROR("Loading db.conf failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,10 @@ target_compile_options(${PROJECT_NAME} PUBLIC -fsigned-char)
|
||||
find_package(unofficial-libmysql REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} unofficial::libmysql::libmysql)
|
||||
|
||||
# Argon2
|
||||
find_package(unofficial-argon2 CONFIG REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} unofficial::argon2::libargon2)
|
||||
|
||||
# Crypto++
|
||||
find_package(cryptopp CONFIG REQUIRED)
|
||||
target_link_libraries (${PROJECT_NAME} cryptopp::cryptopp)
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
#ifndef __WIN32__
|
||||
#include <ifaddrs.h>
|
||||
@ -292,7 +294,7 @@ void config_init(const string& st_localeServiceName)
|
||||
string st_configFileName;
|
||||
|
||||
st_configFileName.reserve(32);
|
||||
st_configFileName = "CONFIG";
|
||||
st_configFileName = "game.conf";
|
||||
|
||||
if (!st_localeServiceName.empty())
|
||||
{
|
||||
@ -342,139 +344,151 @@ void config_init(const string& st_localeServiceName)
|
||||
bool isCommonSQL = false;
|
||||
bool isPlayerSQL = false;
|
||||
|
||||
FILE* fpOnlyForDB;
|
||||
const std::string config_keys[] = {
|
||||
"BLOCK_LOGIN",
|
||||
"ADMINPAGE_IP",
|
||||
"ADMINPAGE_IP1",
|
||||
"ADMINPAGE_IP2",
|
||||
"ADMINPAGE_IP3",
|
||||
"ADMINPAGE_PASSWORD",
|
||||
"HOSTNAME",
|
||||
"CHANNEL",
|
||||
"PLAYER_SQL",
|
||||
"COMMON_SQL",
|
||||
"LOG_SQL"
|
||||
};
|
||||
|
||||
if (!(fpOnlyForDB = fopen(st_configFileName.c_str(), "r")))
|
||||
{
|
||||
SPDLOG_CRITICAL("Can not open [{}]", st_configFileName);
|
||||
exit(EXIT_FAILURE);
|
||||
// Container to store the config file key-value pairs
|
||||
std::unordered_map<std::string, std::string> cfg_file_entries;
|
||||
// Container to store the final config with env overrides
|
||||
std::unordered_map<std::string, std::string> config;
|
||||
|
||||
// Open the file
|
||||
std::ifstream config_file(st_configFileName);
|
||||
|
||||
// Check if the file is open
|
||||
if (!config_file.is_open()) {
|
||||
SPDLOG_WARN("Error opening config file, can't fall back for missing envs.");
|
||||
} else {
|
||||
std::string line;
|
||||
// Read the config file
|
||||
while (std::getline(config_file, line)) {
|
||||
std::istringstream line_stream(line);
|
||||
std::string key;
|
||||
|
||||
// Get the key
|
||||
if (std::getline(line_stream, key, ':')) {
|
||||
std::string value;
|
||||
|
||||
// Get the value
|
||||
if (std::getline(line_stream >> std::ws, value)) {
|
||||
// Store the key and value in the map
|
||||
cfg_file_entries[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
config_file.close();
|
||||
}
|
||||
|
||||
while (fgets(buf, 256, fpOnlyForDB))
|
||||
for (auto& config_key : config_keys) {
|
||||
// Check if the key is an environment variable
|
||||
const char* envValue = std::getenv(config_key.c_str());
|
||||
if (envValue) {
|
||||
// Update the value in the map with the environment variable value
|
||||
config[config_key] = envValue;
|
||||
continue;
|
||||
}
|
||||
// Fallback to config file entries when there's no env override
|
||||
if (cfg_file_entries.find(config_key) != cfg_file_entries.end()){
|
||||
config[config_key] = cfg_file_entries[config_key];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& kvp : config) {
|
||||
SPDLOG_INFO("{}: {}", kvp.first.c_str(), kvp.second.c_str());
|
||||
}
|
||||
|
||||
g_stBlockDate = config["BLOCK_LOGIN"];
|
||||
|
||||
g_stAdminPageIP.push_back(config["ADMINPAGE_IP"]);
|
||||
g_stAdminPageIP.push_back(config["ADMINPAGE_IP1"]);
|
||||
g_stAdminPageIP.push_back(config["ADMINPAGE_IP2"]);
|
||||
g_stAdminPageIP.push_back(config["ADMINPAGE_IP3"]);
|
||||
|
||||
g_stAdminPagePassword = config["ADMINPAGE_PASSWORD"];
|
||||
|
||||
g_stHostname = config["HOSTNAME"];
|
||||
SPDLOG_INFO("HOSTNAME: {}", g_stHostname);
|
||||
|
||||
str_to_number(g_bChannel, config["CHANNEL"].c_str());
|
||||
|
||||
{
|
||||
parse_token(buf, token_string, value_string);
|
||||
const char * line = two_arguments(config["PLAYER_SQL"].c_str(), db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
|
||||
line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
|
||||
|
||||
TOKEN("BLOCK_LOGIN")
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
g_stBlockDate = value_string;
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(mysql_db_port[0], buf);
|
||||
}
|
||||
|
||||
TOKEN("adminpage_ip")
|
||||
if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
|
||||
{
|
||||
FN_add_adminpageIP(value_string);
|
||||
//g_stAdminPageIP[0] = value_string;
|
||||
SPDLOG_CRITICAL("PLAYER_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
TOKEN("adminpage_ip1")
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[0], db_user[0], db_pwd[0], db_db[0], mysql_db_port[0]);
|
||||
isPlayerSQL = true;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const char * line = two_arguments(config["COMMON_SQL"].c_str(), db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
|
||||
line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
|
||||
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
FN_add_adminpageIP(value_string);
|
||||
//g_stAdminPageIP[0] = value_string;
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(mysql_db_port[1], buf);
|
||||
}
|
||||
|
||||
TOKEN("adminpage_ip2")
|
||||
if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
|
||||
{
|
||||
FN_add_adminpageIP(value_string);
|
||||
//g_stAdminPageIP[1] = value_string;
|
||||
SPDLOG_CRITICAL("COMMON_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
TOKEN("adminpage_ip3")
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "COMMON_SQL: %s %s %s %s %d", db_host[1], db_user[1], db_pwd[1], db_db[1], mysql_db_port[1]);
|
||||
isCommonSQL = true;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
const char * line = two_arguments(config["LOG_SQL"].c_str(), log_host, sizeof(log_host), log_user, sizeof(log_user));
|
||||
line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
|
||||
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
FN_add_adminpageIP(value_string);
|
||||
//g_stAdminPageIP[2] = value_string;
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(log_port, buf);
|
||||
}
|
||||
|
||||
TOKEN("adminpage_password")
|
||||
if (!*log_host || !*log_user || !*log_pwd || !*log_db)
|
||||
{
|
||||
g_stAdminPagePassword = value_string;
|
||||
SPDLOG_CRITICAL("LOG_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
TOKEN("hostname")
|
||||
{
|
||||
g_stHostname = value_string;
|
||||
SPDLOG_INFO("HOSTNAME: {}", g_stHostname);
|
||||
continue;
|
||||
}
|
||||
|
||||
TOKEN("channel")
|
||||
{
|
||||
str_to_number(g_bChannel, value_string);
|
||||
continue;
|
||||
}
|
||||
|
||||
TOKEN("player_sql")
|
||||
{
|
||||
const char * line = two_arguments(value_string, db_host[0], sizeof(db_host[0]), db_user[0], sizeof(db_user[0]));
|
||||
line = two_arguments(line, db_pwd[0], sizeof(db_pwd[0]), db_db[0], sizeof(db_db[0]));
|
||||
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(mysql_db_port[0], buf);
|
||||
}
|
||||
|
||||
if (!*db_host[0] || !*db_user[0] || !*db_pwd[0] || !*db_db[0])
|
||||
{
|
||||
SPDLOG_CRITICAL("PLAYER_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "PLAYER_SQL: %s %s %s %s %d", db_host[0], db_user[0], db_pwd[0], db_db[0], mysql_db_port[0]);
|
||||
isPlayerSQL = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
TOKEN("common_sql")
|
||||
{
|
||||
const char * line = two_arguments(value_string, db_host[1], sizeof(db_host[1]), db_user[1], sizeof(db_user[1]));
|
||||
line = two_arguments(line, db_pwd[1], sizeof(db_pwd[1]), db_db[1], sizeof(db_db[1]));
|
||||
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(mysql_db_port[1], buf);
|
||||
}
|
||||
|
||||
if (!*db_host[1] || !*db_user[1] || !*db_pwd[1] || !*db_db[1])
|
||||
{
|
||||
SPDLOG_CRITICAL("COMMON_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "COMMON_SQL: %s %s %s %s %d", db_host[1], db_user[1], db_pwd[1], db_db[1], mysql_db_port[1]);
|
||||
isCommonSQL = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
TOKEN("log_sql")
|
||||
{
|
||||
const char * line = two_arguments(value_string, log_host, sizeof(log_host), log_user, sizeof(log_user));
|
||||
line = two_arguments(line, log_pwd, sizeof(log_pwd), log_db, sizeof(log_db));
|
||||
|
||||
if ('\0' != line[0])
|
||||
{
|
||||
char buf[256];
|
||||
one_argument(line, buf, sizeof(buf));
|
||||
str_to_number(log_port, buf);
|
||||
}
|
||||
|
||||
if (!*log_host || !*log_user || !*log_pwd || !*log_db)
|
||||
{
|
||||
SPDLOG_CRITICAL("LOG_SQL syntax: logsql <host user password db>");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//처리가 끝났으니 파일을 닫자.
|
||||
fclose(fpOnlyForDB);
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof(buf), "LOG_SQL: %s %s %s %s %d", log_host, log_user, log_pwd, log_db, log_port);
|
||||
}
|
||||
|
||||
// CONFIG_SQL_INFO_ERROR
|
||||
if (!isCommonSQL)
|
||||
@ -775,19 +789,27 @@ void config_init(const string& st_localeServiceName)
|
||||
|
||||
TOKEN("test_server")
|
||||
{
|
||||
printf("-----------------------------------------------\n");
|
||||
printf("TEST_SERVER\n");
|
||||
printf("-----------------------------------------------\n");
|
||||
str_to_number(test_server, value_string);
|
||||
|
||||
if (test_server) {
|
||||
printf("-----------------------------------------------\n");
|
||||
printf("TEST_SERVER\n");
|
||||
printf("-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
TOKEN("speed_server")
|
||||
{
|
||||
printf("-----------------------------------------------\n");
|
||||
printf("SPEED_SERVER\n");
|
||||
printf("-----------------------------------------------\n");
|
||||
str_to_number(speed_server, value_string);
|
||||
|
||||
if (speed_server) {
|
||||
printf("-----------------------------------------------\n");
|
||||
printf("SPEED_SERVER\n");
|
||||
printf("-----------------------------------------------\n");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
#ifdef __AUCTION__
|
||||
@ -887,7 +909,11 @@ void config_init(const string& st_localeServiceName)
|
||||
|
||||
two_arguments(value_string, szIP, sizeof(szIP), szPort, sizeof(szPort));
|
||||
|
||||
if (!*szIP || (!*szPort && strcasecmp(szIP, "master")))
|
||||
// Skip if arguments are empty
|
||||
if (!*szIP)
|
||||
continue;
|
||||
|
||||
if (!*szPort && strcasecmp(szIP, "master"))
|
||||
{
|
||||
SPDLOG_CRITICAL("AUTH_SERVER: syntax error: <ip|master> <port>");
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -1,21 +1,19 @@
|
||||
#include "stdafx.h"
|
||||
#include <sstream>
|
||||
#include <common/length.h>
|
||||
#include <argon2.h>
|
||||
|
||||
#include "db.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "desc_client.h"
|
||||
#include "desc_manager.h"
|
||||
#include "char.h"
|
||||
#include "char_manager.h"
|
||||
#include "item.h"
|
||||
#include "item_manager.h"
|
||||
#include "p2p.h"
|
||||
#include "matrix_card.h"
|
||||
#include "log.h"
|
||||
#include "login_data.h"
|
||||
#include "locale_service.h"
|
||||
#include "spam.h"
|
||||
|
||||
extern std::string g_stBlockDate;
|
||||
@ -275,8 +273,8 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
|
||||
|
||||
if (pMsg->Get()->uiNumRows == 0)
|
||||
{
|
||||
SPDLOG_DEBUG(" NOID");
|
||||
LoginFailure(d, "NOID");
|
||||
SPDLOG_DEBUG(" WRONGCRD");
|
||||
LoginFailure(d, "WRONGCRD");
|
||||
M2_DELETE(pinfo);
|
||||
}
|
||||
else
|
||||
@ -284,31 +282,21 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
|
||||
MYSQL_ROW row = mysql_fetch_row(pMsg->Get()->pSQLResult);
|
||||
int col = 0;
|
||||
|
||||
// PASSWORD('%s'), password, securitycode, social_id, id, status
|
||||
char szEncrytPassword[45 + 1];
|
||||
char szPassword[45 + 1];
|
||||
// password, securitycode, social_id, id, status
|
||||
char szHashedPassword[128 + 1];
|
||||
char szMatrixCode[MATRIX_CODE_MAX_LEN + 1];
|
||||
char szSocialID[SOCIAL_ID_MAX_LEN + 1];
|
||||
char szStatus[ACCOUNT_STATUS_MAX_LEN + 1];
|
||||
DWORD dwID = 0;
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
strlcpy(szEncrytPassword, row[col++], sizeof(szEncrytPassword));
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
strlcpy(szPassword, row[col++], sizeof(szPassword));
|
||||
strlcpy(szHashedPassword, row[col++], sizeof(szHashedPassword));
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
@ -321,29 +309,29 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
|
||||
}
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strlcpy(szSocialID, row[col++], sizeof(szSocialID));
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
str_to_number(dwID, row[col++]);
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
str_to_number(dwID, row[col++]);
|
||||
|
||||
if (!row[col])
|
||||
{
|
||||
SPDLOG_ERROR("error column {}", col);
|
||||
M2_DELETE(pinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
strlcpy(szStatus, row[col++], sizeof(szStatus));
|
||||
|
||||
@ -374,12 +362,12 @@ void DBManager::AnalyzeReturnQuery(SQLMsg * pMsg)
|
||||
SPDLOG_DEBUG("Create_Time {} {}", retValue, szCreateDate);
|
||||
SPDLOG_DEBUG("Block Time {} ", strncmp(szCreateDate, g_stBlockDate.c_str(), 8));
|
||||
|
||||
int nPasswordDiff = strcmp(szEncrytPassword, szPassword);
|
||||
bool loginStatus = argon2id_verify(szHashedPassword, pinfo->passwd, strlen(pinfo->passwd)) == ARGON2_OK;
|
||||
|
||||
if (nPasswordDiff)
|
||||
if (!loginStatus)
|
||||
{
|
||||
LoginFailure(d, "WRONGPWD");
|
||||
SPDLOG_DEBUG(" WRONGPWD");
|
||||
LoginFailure(d, "WRONGCRD");
|
||||
SPDLOG_DEBUG(" WRONGCRD");
|
||||
M2_DELETE(pinfo);
|
||||
}
|
||||
else if (bNotAvail)
|
||||
|
@ -4,9 +4,6 @@
|
||||
#include "input.h"
|
||||
#include "desc_client.h"
|
||||
#include "desc_manager.h"
|
||||
#include "protocol.h"
|
||||
#include "matrix_card.h"
|
||||
#include "locale_service.h"
|
||||
#include "db.h"
|
||||
|
||||
extern time_t get_global_time();
|
||||
@ -33,13 +30,6 @@ bool FN_IS_VALID_LOGIN_STRING(const char *str)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Login_IsInChannelService(const char* c_login)
|
||||
{
|
||||
if (c_login[0] == '[')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
CInputAuth::CInputAuth()
|
||||
{
|
||||
}
|
||||
@ -55,7 +45,7 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
|
||||
return;
|
||||
}
|
||||
|
||||
// string 무결성을 위해 복사
|
||||
// Copy for string integrity
|
||||
char login[LOGIN_MAX_LEN + 1];
|
||||
trim_and_lower(pinfo->login, login, sizeof(login));
|
||||
|
||||
@ -70,7 +60,7 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
|
||||
{
|
||||
SPDLOG_DEBUG("InputAuth::Login : IS_NOT_VALID_LOGIN_STRING({}) desc {}",
|
||||
login, (void*) get_pointer(d));
|
||||
LoginFailure(d, "NOID");
|
||||
LoginFailure(d, "WRONGCRD");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -100,47 +90,21 @@ void CInputAuth::Login(LPDESC d, const char * c_pData)
|
||||
TPacketCGLogin3 * p = M2_NEW TPacketCGLogin3;
|
||||
memcpy(p, pinfo, sizeof(TPacketCGLogin3));
|
||||
|
||||
char szPasswd[PASSWD_MAX_LEN * 2 + 1];
|
||||
DBManager::instance().EscapeString(szPasswd, sizeof(szPasswd), passwd, strlen(passwd));
|
||||
|
||||
char szLogin[LOGIN_MAX_LEN * 2 + 1];
|
||||
DBManager::instance().EscapeString(szLogin, sizeof(szLogin), login, strlen(login));
|
||||
|
||||
// CHANNEL_SERVICE_LOGIN
|
||||
if (Login_IsInChannelService(szLogin))
|
||||
{
|
||||
SPDLOG_DEBUG("ChannelServiceLogin [{}]", szLogin);
|
||||
|
||||
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
|
||||
"SELECT '%s',password,securitycode,social_id,id,status,availDt - NOW() > 0,"
|
||||
"UNIX_TIMESTAMP(silver_expire),"
|
||||
"UNIX_TIMESTAMP(gold_expire),"
|
||||
"UNIX_TIMESTAMP(safebox_expire),"
|
||||
"UNIX_TIMESTAMP(autoloot_expire),"
|
||||
"UNIX_TIMESTAMP(fish_mind_expire),"
|
||||
"UNIX_TIMESTAMP(marriage_fast_expire),"
|
||||
"UNIX_TIMESTAMP(money_drop_rate_expire),"
|
||||
"UNIX_TIMESTAMP(create_time)"
|
||||
" FROM account WHERE login='%s'",
|
||||
|
||||
szPasswd, szLogin);
|
||||
}
|
||||
// END_OF_CHANNEL_SERVICE_LOGIN
|
||||
else
|
||||
{
|
||||
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
|
||||
"SELECT PASSWORD('%s'),password,securitycode,social_id,id,status,availDt - NOW() > 0,"
|
||||
"UNIX_TIMESTAMP(silver_expire),"
|
||||
"UNIX_TIMESTAMP(gold_expire),"
|
||||
"UNIX_TIMESTAMP(safebox_expire),"
|
||||
"UNIX_TIMESTAMP(autoloot_expire),"
|
||||
"UNIX_TIMESTAMP(fish_mind_expire),"
|
||||
"UNIX_TIMESTAMP(marriage_fast_expire),"
|
||||
"UNIX_TIMESTAMP(money_drop_rate_expire),"
|
||||
"UNIX_TIMESTAMP(create_time)"
|
||||
" FROM account WHERE login='%s'",
|
||||
szPasswd, szLogin);
|
||||
}
|
||||
DBManager::instance().ReturnQuery(QID_AUTH_LOGIN, dwKey, p,
|
||||
"SELECT password,securitycode,social_id,id,status,availDt - NOW() > 0,"
|
||||
"UNIX_TIMESTAMP(silver_expire),"
|
||||
"UNIX_TIMESTAMP(gold_expire),"
|
||||
"UNIX_TIMESTAMP(safebox_expire),"
|
||||
"UNIX_TIMESTAMP(autoloot_expire),"
|
||||
"UNIX_TIMESTAMP(fish_mind_expire),"
|
||||
"UNIX_TIMESTAMP(marriage_fast_expire),"
|
||||
"UNIX_TIMESTAMP(money_drop_rate_expire),"
|
||||
"UNIX_TIMESTAMP(create_time)"
|
||||
" FROM account WHERE login='%s'",
|
||||
szLogin);
|
||||
}
|
||||
|
||||
int CInputAuth::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
|
||||
|
@ -26,11 +26,9 @@
|
||||
#include "building.h"
|
||||
#include "login_sim.h"
|
||||
#include "wedding.h"
|
||||
#include "login_data.h"
|
||||
#include "unique_item.h"
|
||||
|
||||
#include "monarch.h"
|
||||
#include "affect.h"
|
||||
#include "castle.h"
|
||||
#include "motion.h"
|
||||
|
||||
@ -1956,11 +1954,11 @@ int CInputDB::Analyze(LPDESC d, BYTE bHeader, const char * c_pData)
|
||||
break;
|
||||
|
||||
case HEADER_DG_LOGIN_NOT_EXIST:
|
||||
LoginFailure(DESC_MANAGER::instance().FindByHandle(m_dwHandle), "NOID");
|
||||
LoginFailure(DESC_MANAGER::instance().FindByHandle(m_dwHandle), "WRONGCRD");
|
||||
break;
|
||||
|
||||
case HEADER_DG_LOGIN_WRONG_PASSWD:
|
||||
LoginFailure(DESC_MANAGER::instance().FindByHandle(m_dwHandle), "WRONGPWD");
|
||||
LoginFailure(DESC_MANAGER::instance().FindByHandle(m_dwHandle), "WRONGCRD");
|
||||
break;
|
||||
|
||||
case HEADER_DG_LOGIN_ALREADY:
|
||||
|
Reference in New Issue
Block a user