public LoginResponse Login(User user, Login login, Client client)
        {
            string ip           = client.RemoteEndpointIP;
            long   userID       = login.UserID;
            string lobbyVersion = login.LobbyVersion;

            using (var db = new ZkDataContext()) {
                Account acc = db.Accounts.Include(x => x.Clan).Include(x => x.Faction).FirstOrDefault(x => x.Name == login.Name);
                if (acc == null)
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.InvalidName
                    }
                }
                ;
                if (!acc.VerifyPassword(login.PasswordHash))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.InvalidPassword
                    }
                }
                ;
                if (state.Clients.ContainsKey(login.Name))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.AlreadyConnected
                    }
                }
                ;

                acc.Country      = ResolveCountry(ip);
                acc.LobbyVersion = lobbyVersion;
                acc.LastLogin    = DateTime.UtcNow;

                user.ClientType   = login.ClientType;
                user.LobbyVersion = login.LobbyVersion;
                UpdateUserFromAccount(user, acc);

                LogIP(db, acc, ip);

                LogUserID(db, acc, userID);

                db.SaveChanges();


                var banMute = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanMute, db);
                if (banMute != null)
                {
                    user.BanMute = true;
                }


                Punishment banPenalty = Punishment.GetActivePunishment(acc.AccountID, ip, userID, x => x.BanLobby, db);

                if (banPenalty != null)
                {
                    return
                        (BlockLogin(
                             string.Format("Banned until {0} (match to {1}), reason: {2}", banPenalty.BanExpires, banPenalty.AccountByAccountID.Name,
                                           banPenalty.Reason), acc, ip, userID));
                }

                Account accAnteep = db.Accounts.FirstOrDefault(x => x.AccountID == 4490);
                if (accAnteep != null)
                {
                    if (accAnteep.AccountUserIDs.Any(y => y.UserID == userID))
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (ID match {1}) {2}", acc.Name, userID,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }

                    if (userID > 0 && userID < 1000)
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (too short userID {1}) {2}", acc.Name, userID,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }

                    if (accAnteep.AccountIPs.Any(y => y.IP == ip))
                    {
                        Talk(String.Format("Suspected Anteep smurf: {0} (IP match {1}) {2}", acc.Name, ip,
                                           string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                    }
                }

                if (!acc.HasVpnException && GlobalConst.VpnCheckEnabled)
                {
                    // check user IP against http://dnsbl.tornevall.org
                    // does not catch all smurfs
                    // mostly false positives, do not use
                    string reversedIP = string.Join(".", ip.Split('.').Reverse().ToArray());
                    try {
                        IPAddress[] resolved = Dns.GetHostEntry(string.Format("{0}.dnsbl.tornevall.org", reversedIP)).AddressList;
                        if (resolved.Length > 0)
                        {
                            Talk(String.Format("User {0} {3} has IP {1} on dnsbl.tornevall.org ({2} result/s)", acc.Name, ip, resolved.Length,
                                               string.Format("{1}/Users/Detail/{0}", acc.AccountID, GlobalConst.BaseSiteUrl)));
                        }
                    } catch (SocketException sockEx) {
                        // not in database, do nothing
                    }
                }

                try {
                    if (!acc.HasVpnException)
                    {
                        for (int i = 0; i <= 1; i++)
                        {
                            var whois = new Whois();
                            Dictionary <string, string> data = whois.QueryByIp(ip, i == 1);

                            if (!data.ContainsKey("netname"))
                            {
                                data["netname"] = "UNKNOWN NETNAME";
                            }
                            if (!data.ContainsKey("org-name"))
                            {
                                data["org-name"] = "UNKNOWN ORG";
                            }
                            if (!data.ContainsKey("abuse-mailbox"))
                            {
                                data["abuse-mailbox"] = "no mailbox";
                            }
                            if (!data.ContainsKey("notify"))
                            {
                                data["notify"] = "no notify address";
                            }
                            if (!data.ContainsKey("role"))
                            {
                                data["role"] = "UNKNOWN ROLE";
                            }
                            if (!data.ContainsKey("descr"))
                            {
                                data["descr"] = "no description";
                            }
                            if (!data.ContainsKey("remarks"))
                            {
                                data["remarks"] = "no remarks";
                            }

                            List <string> blockedCompanies = db.BlockedCompanies.Select(x => x.CompanyName.ToLower()).ToList();
                            List <string> blockedHosts     = db.BlockedHosts.Select(x => x.HostName).ToList();

                            /*if (acc.Country == "MY")
                             * {
                             * client.Say(SayPlace.User, "KingRaptor", String.Format("USER {0}\nnetname: {1}\norgname: {2}\ndescr: {3}\nabuse-mailbox: {4}",
                             *  acc.Name, data["netname"], data["org-name"], data["descr"], data["abuse-mailbox"]), false);
                             * }*/

                            bool blockedHost = blockedHosts.Any(x => data["abuse-mailbox"].Contains(x)) ||
                                               (blockedHosts.Any(x => data["notify"].Contains(x)));

                            foreach (string company in blockedCompanies)
                            {
                                if (data["netname"].ToLower().Contains(company) || data["org-name"].ToLower().Contains(company) ||
                                    data["descr"].ToLower().Contains(company) || data["role"].ToLower().Contains(company) ||
                                    data["remarks"].ToLower().Contains(company))
                                {
                                    blockedHost = true;
                                    break;
                                }
                            }

                            string hostname = Dns.GetHostEntry(ip).HostName;
                            if (blockedHosts.Any(hostname.Contains))
                            {
                                blockedHost = true;
                            }

                            if (blockedHost)
                            {
                                return(BlockLogin("Connection using proxy or VPN is not allowed! (You can ask for exception)", acc, ip, userID));
                            }
                        }
                    }
                } catch (SocketException sockEx) {} catch (Exception ex) {
                    Trace.TraceError("VPN check error: {0}", ex);
                }

                if (state.Clients.TryAdd(login.Name, client))
                {
                    return new LoginResponse {
                               ResultCode = LoginResponse.Code.Ok
                    }
                }
                ;
                else
                {
                    return new LoginResponse()
                           {
                               ResultCode = LoginResponse.Code.AlreadyConnected
                           }
                };
            }
        }

        string ResolveCountry(string ip)
        {
            if (IsLanIP(ip))
            {
                return("CZ");
            }
            else
            {
                try {
                    return(geoIP.Country(ip).Country.IsoCode);
                } catch (Exception ex) {
                    Trace.TraceWarning("{0} Unable to resolve country", this);
                    return("??");
                }
            }
        }

        LoginResponse BlockLogin(string reason, Account acc, string ip, long user_id)
        {
            Talk(string.Format("Login denied for {0} IP:{1} ID:{2} reason: {3}", acc.Name, ip, user_id, reason));
            return(new LoginResponse {
                Reason = reason, ResultCode = LoginResponse.Code.Banned
            });
        }