1 /*
2 * The ManaPlus Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2010 The Mana Developers
5 * Copyright (C) 2011-2019 The ManaPlus Developers
6 * Copyright (C) 2019-2021 Andrei Karas
7 *
8 * This file is part of The ManaPlus Client.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "net/tmwa/loginrecv.h"
25
26 #include "client.h"
27 #include "configuration.h"
28 #include "logger.h"
29
30 #include "being/being.h"
31
32 #include "net/logindata.h"
33 #include "net/loginhandler.h"
34 #include "net/messagein.h"
35
36 #include "net/ea/loginrecv.h"
37
38 #include "net/tmwa/updateprotocol.h"
39
40 #include "utils/gettext.h"
41
42 #include "debug.h"
43
44 extern int packetVersion;
45 extern int itemIdLen;
46
47 namespace TmwAthena
48 {
49
50 extern ServerInfo charServer;
51
52 enum ServerFlags
53 {
54 FLAG_REGISTRATION = 1
55 };
56
processServerVersion(Net::MessageIn & msg)57 void LoginRecv::processServerVersion(Net::MessageIn &msg)
58 {
59 packetVersion = 0;
60 itemIdLen = 2;
61 const uint8_t b1 = msg.readUInt8("b1"); // -1
62 const uint8_t b2 = msg.readUInt8("b2");
63 const uint8_t b3 = msg.readUInt8("b3");
64 msg.readUInt8("b4");
65 if (b1 == 255)
66 { // old TMWA
67 const unsigned int options = msg.readInt32("options");
68 Ea::LoginRecv::mRegistrationEnabled =
69 ((options & FLAG_REGISTRATION) != 0U);
70 serverVersion = 0;
71 tmwServerVersion = 0;
72 }
73 else if (b1 >= 0x0d)
74 { // new TMWA
75 const unsigned int options = msg.readInt32("options");
76 Ea::LoginRecv::mRegistrationEnabled =
77 ((options & FLAG_REGISTRATION) != 0U);
78 serverVersion = 0;
79 tmwServerVersion = (b1 << 16) | (b2 << 8) | b3;
80 }
81 else
82 { // eAthena
83 const unsigned int options = msg.readInt32("options");
84 Ea::LoginRecv::mRegistrationEnabled =
85 ((options & FLAG_REGISTRATION) != 0U);
86 serverVersion = 0;
87 tmwServerVersion = 0;
88 }
89 if (tmwServerVersion > 0)
90 logger->log("Tmw server version: x%06x", tmwServerVersion);
91 else
92 logger->log("Server without version");
93 updateProtocol();
94
95 if (client->getState() != State::LOGIN)
96 client->setState(State::LOGIN);
97
98 // Leave this last
99 Ea::LoginRecv::mVersionResponse = true;
100 }
101
processCharPasswordResponse(Net::MessageIn & msg)102 void LoginRecv::processCharPasswordResponse(Net::MessageIn &msg)
103 {
104 // 0: acc not found, 1: success, 2: password mismatch, 3: pass too short
105 const uint8_t errMsg = msg.readUInt8("result code");
106 // Successful pass change
107 if (errMsg == 1)
108 {
109 client->setState(State::CHANGEPASSWORD_SUCCESS);
110 }
111 // pass change failed
112 else
113 {
114 switch (errMsg)
115 {
116 case 0:
117 errorMessage =
118 // TRANSLATORS: error message
119 _("Account was not found. Please re-login.");
120 break;
121 case 2:
122 // TRANSLATORS: error message
123 errorMessage = _("Old password incorrect.");
124 break;
125 case 3:
126 // TRANSLATORS: error message
127 errorMessage = _("New password too short.");
128 break;
129 default:
130 // TRANSLATORS: error message
131 errorMessage = _("Unknown error.");
132 break;
133 }
134 client->setState(State::ACCOUNTCHANGE_ERROR);
135 }
136 }
137
processLoginData(Net::MessageIn & msg)138 void LoginRecv::processLoginData(Net::MessageIn &msg)
139 {
140 msg.readInt16("len");
141
142 loginHandler->clearWorlds();
143
144 const int worldCount = (msg.getLength() - 47) / 32;
145
146 Ea::LoginRecv::mToken.session_ID1 = msg.readInt32("session id1");
147 Ea::LoginRecv::mToken.account_ID = msg.readBeingId("accound id");
148 Ea::LoginRecv::mToken.session_ID2 = msg.readInt32("session id2");
149 msg.readInt32("old ip");
150 loginData.lastLogin = msg.readString(24, "last login");
151 msg.readInt16("unused");
152
153 // reserve bits for future usage
154 Ea::LoginRecv::mToken.sex = Being::intToGender(CAST_U8(
155 msg.readUInt8("gender") & 3U));
156
157 for (int i = 0; i < worldCount; i++)
158 {
159 WorldInfo *const world = new WorldInfo;
160
161 world->address = msg.readInt32("ip address");
162 world->port = msg.readInt16("port");
163 world->name = msg.readString(20, "name");
164 world->online_users = msg.readInt16("online number");
165 config.setValue("updatehost", Ea::LoginRecv::mUpdateHost);
166 world->updateHost = Ea::LoginRecv::mUpdateHost;
167 msg.readInt16("maintenance");
168 msg.readInt16("new");
169
170 logger->log("Network: Server: %s (%s:%d)", world->name.c_str(),
171 ipToString(world->address), world->port);
172
173 Ea::LoginRecv::mWorlds.push_back(world);
174 }
175 client->setState(State::WORLD_SELECT);
176 }
177
178 } // namespace TmwAthena
179