191 | | ASSERT (s); |
192 | | |
193 | | //NOTE - Still there is race condition in WorldSession* being used in the Sockets |
194 | | |
195 | | ///- kick already loaded player with same account (if any) and remove session |
196 | | ///- if player is in loading and want to load again, return |
197 | | if (!RemoveSession (s->GetAccountId ())) |
198 | | { |
199 | | s->KickPlayer (); |
200 | | m_kicked_sessions.insert (s); |
201 | | return; |
202 | | } |
203 | | |
204 | | WorldSession* old = m_sessions[s->GetAccountId ()]; |
205 | | m_sessions[s->GetAccountId ()] = s; |
206 | | |
207 | | // if session already exist, prepare to it deleting at next world update |
208 | | // NOTE - KickPlayer() should be called on "old" in RemoveSession() |
209 | | if (old) |
210 | | m_kicked_sessions.insert (old); |
211 | | |
212 | | uint32 Sessions = GetActiveAndQueuedSessionCount (); |
213 | | uint32 pLimit = GetPlayerAmountLimit (); |
214 | | uint32 QueueSize = GetQueueSize (); //number of players in the queue |
215 | | bool inQueue = false; |
216 | | //so we don't count the user trying to |
217 | | //login as a session and queue the socket that we are using |
218 | | --Sessions; |
219 | | |
220 | | if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) |
221 | | { |
222 | | AddQueuedPlayer (s); |
223 | | UpdateMaxSessionCounters (); |
224 | | sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize); |
225 | | return; |
226 | | } |
227 | | |
228 | | WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); |
229 | | packet << uint8 (AUTH_OK); |
230 | | packet << uint32 (0); // unknown random value... |
231 | | packet << uint8 (0); |
232 | | packet << uint32 (0); |
233 | | packet << uint8 (s->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account |
234 | | s->SendPacket (&packet); |
235 | | |
236 | | UpdateMaxSessionCounters (); |
237 | | |
238 | | // Updates the population |
239 | | if (pLimit > 0) |
240 | | { |
241 | | float popu = GetActiveSessionCount (); //updated number of users on the server |
242 | | popu /= pLimit; |
243 | | popu *= 2; |
244 | | loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); |
245 | | sLog.outDetail ("Server Population (%f).", popu); |
| 191 | ASSERT (s); |
| 192 | |
| 193 | //NOTE - Still there is race condition in WorldSession* being used in the Sockets |
| 194 | |
| 195 | ///- kick already loaded player with same account (if any) and remove session |
| 196 | ///- if player is in loading and want to load again, return |
| 197 | if (!RemoveSession (s->GetAccountId ())) |
| 198 | { |
| 199 | s->KickPlayer (); |
| 200 | m_kicked_sessions.insert (s); |
| 201 | return; |
| 202 | } |
| 203 | |
| 204 | WorldSession* old = m_sessions[s->GetAccountId ()]; |
| 205 | m_sessions[s->GetAccountId ()] = s; |
| 206 | |
| 207 | // if session already exist, prepare to it deleting at next world update |
| 208 | // NOTE - KickPlayer() should be called on "old" in RemoveSession() |
| 209 | if (old) |
| 210 | m_kicked_sessions.insert (old); |
| 211 | |
| 212 | uint32 Sessions = GetActiveAndQueuedSessionCount (); |
| 213 | uint32 pLimit = GetPlayerAmountLimit (); |
| 214 | uint32 QueueSize = GetQueueSize (); //number of players in the queue |
| 215 | bool inQueue = false; |
| 216 | //so we don't count the user trying to |
| 217 | //login as a session and queue the socket that we are using |
| 218 | --Sessions; |
| 219 | |
| 220 | if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER ) |
| 221 | { |
| 222 | AddQueuedPlayer (s); |
| 223 | UpdateMaxSessionCounters (); |
| 224 | sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize); |
| 225 | return; |
| 226 | } |
| 227 | |
| 228 | WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); |
| 229 | packet << uint8 (AUTH_OK); |
| 230 | packet << uint32 (0); // unknown random value... |
| 231 | packet << uint8 (0); |
| 232 | packet << uint32 (0); |
| 233 | packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account |
| 234 | s->SendPacket (&packet); |
| 235 | |
| 236 | UpdateMaxSessionCounters (); |
| 237 | |
| 238 | // Updates the population |
| 239 | if (pLimit > 0) |
| 240 | { |
| 241 | float popu = GetActiveSessionCount (); //updated number of users on the server |
| 242 | popu /= pLimit; |
| 243 | popu *= 2; |
| 244 | loginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); |
| 245 | sLog.outDetail ("Server Population (%f).", popu); |
2288 | | //No SQL injection as strings are escaped |
2289 | | resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); |
2290 | | loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); |
2291 | | break; |
2292 | | case BAN_ACCOUNT: |
2293 | | //No SQL injection as string is escaped |
2294 | | resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); |
2295 | | break; |
2296 | | case BAN_CHARACTER: |
2297 | | //No SQL injection as string is escaped |
2298 | | resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); |
2299 | | break; |
2300 | | default: |
2301 | | return BAN_SYNTAX_ERROR; |
2302 | | } |
2303 | | |
2304 | | if(!resultAccounts) |
2305 | | { |
2306 | | if(mode==BAN_IP) |
2307 | | return BAN_SUCCESS; |
2308 | | else |
2309 | | return BAN_NOTFOUND; // Nobody to ban |
2310 | | } |
| 2288 | //No SQL injection as strings are escaped |
| 2289 | resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'",nameOrIP.c_str()); |
| 2290 | loginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')",nameOrIP.c_str(),duration_secs,safe_author.c_str(),reason.c_str()); |
| 2291 | break; |
| 2292 | case BAN_ACCOUNT: |
| 2293 | //No SQL injection as string is escaped |
| 2294 | resultAccounts = loginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'",nameOrIP.c_str()); |
| 2295 | break; |
| 2296 | case BAN_CHARACTER: |
| 2297 | //No SQL injection as string is escaped |
| 2298 | resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'",nameOrIP.c_str()); |
| 2299 | break; |
| 2300 | default: |
| 2301 | return BAN_SYNTAX_ERROR; |
| 2302 | } |
| 2303 | |
| 2304 | if(!resultAccounts) |
| 2305 | { |
| 2306 | if(mode==BAN_IP) |
| 2307 | return BAN_SUCCESS; // ip correctly banned but nobody affected (yet) |
| 2308 | else |
| 2309 | return BAN_NOTFOUND; // Nobody to ban |
| 2310 | } |