diff --git a/nge.backup b/nge.backup index 049637b4..6dd9ec23 100644 Binary files a/nge.backup and b/nge.backup differ diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 1e25ed4e..5f2b323b 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -34,6 +34,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import org.apache.mina.core.service.IoHandler; import net.engio.mbassy.bus.config.BusConfiguration; import resources.common.RadialOptions; import resources.common.ThreadMonitor; @@ -64,6 +65,7 @@ import services.command.CommandService; import services.gcw.FactionService; import services.gcw.GCWService; import services.guild.GuildService; +import services.LoginService; import services.map.MapService; import services.object.ObjectService; import services.object.UpdateService; @@ -90,7 +92,9 @@ import engine.resources.database.ObjectDatabase; import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; +import engine.resources.service.InteractiveJythonAcceptor; import engine.resources.service.NetworkDispatch; +import engine.servers.InteractiveJythonServer; import engine.servers.MINAServer; import engine.servers.PingServer; @@ -153,6 +157,10 @@ public class NGECore { // Zone Server public NetworkDispatch zoneDispatch; private MINAServer zoneServer; + + // Interactive Jython Console + public InteractiveJythonAcceptor jythonAcceptor; + private InteractiveJythonServer jythonServer; private ObjectDatabase creatureODB; private ObjectDatabase mailODB; @@ -189,12 +197,18 @@ public class NGECore { // Database databaseConnection = new DatabaseConnection(); databaseConnection.connect(config.getString("DB.URL"), config.getString("DB.NAME"), config.getString("DB.USER"), config.getString("DB.PASS"), "postgresql"); + + String db2Url = config.getString("DB2.URL"); + if (db2Url == null || db2Url.matches("^\\s*$")) { + databaseConnection2 = null; + } else { + databaseConnection2 = new DatabaseConnection(); + databaseConnection2.connect(config.getString("DB2.URL"), config.getString("DB2.NAME"), config.getString("DB2.USER"), config.getString("DB2.PASS"), "mysql"); + } - databaseConnection2 = new DatabaseConnection(); setGalaxyStatus(1); creatureODB = new ObjectDatabase("creature", true, false, true); mailODB = new ObjectDatabase("mails", true, false, true); - // Services loginService = new LoginService(this); connectionService = new ConnectionService(this); @@ -219,6 +233,19 @@ public class NGECore { skillModService = new SkillModService(this); equipmentService = new EquipmentService(this); entertainmentService = new EntertainmentService(this); + + if (config.keyExists("JYTHONCONSOLE.PORT")) { + int jythonPort = config.getInt("JYTHONCONSOLE.PORT"); + if (jythonPort > 0) { + + System.out.println("Starting InteractiveJythonServer on Port " + jythonPort); + jythonAcceptor = new InteractiveJythonAcceptor(); + jythonServer = new InteractiveJythonServer((IoHandler) jythonAcceptor, jythonPort, this); + jythonAcceptor.setServer(jythonServer); + jythonServer.start(); + } + } + spawnService = new SpawnService(this); aiService = new AIService(this); //missionService = new MissionService(this); @@ -314,8 +341,6 @@ public class NGECore { setGalaxyStatus(2); } - - public void stop() { System.out.println("Stopping Servers and Connections."); diff --git a/src/protocol/Message.java b/src/protocol/Message.java index 5085a975..9792eaec 100644 --- a/src/protocol/Message.java +++ b/src/protocol/Message.java @@ -103,6 +103,7 @@ public abstract class Message { } + //TODO: Verify if character position is set correctly after reading a UTF-16 string buffer.position(bufferPosition + length); return result; @@ -146,8 +147,8 @@ public abstract class Message { return result.array(); } - - + + //FIXME: this is redundant and was also bugged. At some point, get rid of the redundant functions. /** * Reads the next string in. It gets the length of the * string from the short/int at the beginning of it @@ -161,7 +162,7 @@ public abstract class Message { if (charset.equals("US-ASCII") || charset.equals("UTF-8")) { length = bb.getShort(); } else { - length = bb.getInt(); + length = bb.getInt() * 2; } if (length > bb.remaining()) return ""; @@ -201,4 +202,4 @@ public abstract class Message { return getNextString(buffer, "UTF-16LE"); } -} +} diff --git a/src/protocol/swg/ClientVerifyAndLockNameRequest.java b/src/protocol/swg/ClientVerifyAndLockNameRequest.java index 7d9c9722..ea0011f5 100644 --- a/src/protocol/swg/ClientVerifyAndLockNameRequest.java +++ b/src/protocol/swg/ClientVerifyAndLockNameRequest.java @@ -38,8 +38,8 @@ public class ClientVerifyAndLockNameRequest extends SWGMessage { public void deserialize(IoBuffer buffer) { buffer.position(6); // Skips SOE and SWG opcodes raceTemplate = getNextAsciiString(buffer); - name = getNextUnicodeString(buffer);; - + name = getNextUnicodeString(buffer); + System.out.println("msg: " + name); // Gets the first and last names String [] splitName = name.split(" "); firstName = splitName[0]; diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index b218c901..df850ddf 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -1381,6 +1381,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { synchronized(objectMutex) { this.performanceWatchee = performanceWatchee; } + // not sure at this point if it makes a difference really. + // on Live, an empty CREO4 was sent, at least when listenToId was empty. //getClient().getSession().write(messageBuilder.buildListenToId(0)); } diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index a4d45d4b..1be62a7a 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -87,6 +87,7 @@ public class CharacterService implements INetworkDispatch { swgOpcodes.put(Opcodes.ClientRandomNameRequest, new INetworkRemoteEvent() { public void handlePacket(IoSession session, IoBuffer data) throws Exception { + ClientRandomNameRequest randomNameRequest = new ClientRandomNameRequest(); ClientRandomNameResponse response; String name = null; @@ -95,16 +96,23 @@ public class CharacterService implements INetworkDispatch { data.position(0); randomNameRequest.deserialize(data); + while (name == null) { + + String firstName =""; + String lastName = ""; if (randomNameRequest.getSharedRaceTemplate().contains("wookie")) { - name = nameGenerator.compose(4); + firstName = nameGenerator.compose(4); + } else { - name = nameGenerator.compose(2) + " " + nameGenerator.compose(3); + firstName = nameGenerator.compose(2); + lastName = nameGenerator.compose(3); } try { - if (checkForDuplicateName(getfirstName(name, randomNameRequest.getSharedRaceTemplate()))) { - name = null; + //it's fine here to just use 0 as accountId because we don't want reserved names to be random generated for anyone. + if (!checkForDuplicateName(firstName, 0)) { + name = firstName + ((lastName.length() > 0 ) ? " " + lastName : ""); } } catch (SQLException e2) { e2.printStackTrace(); @@ -121,6 +129,8 @@ public class CharacterService implements INetworkDispatch { @Override public void handlePacket(IoSession session, IoBuffer data) throws Exception { + + Client client = core.getClient((Integer) session.getAttribute("connectionId")); data = data.order(ByteOrder.LITTLE_ENDIAN); data.position(0); ClientVerifyAndLockNameRequest message = new ClientVerifyAndLockNameRequest(); @@ -129,11 +139,11 @@ public class CharacterService implements INetworkDispatch { boolean isDeclined = false; String firstName = getfirstName(message.getName(), message.getRaceTemplate()); String lastName = getlastName(message.getName(), message.getRaceTemplate()); - if(message.getName() != null) System.out.println(message.getName()); + //if(message.getName() != null) System.out.println(message.getName()); int length = firstName.length(); try { - if (checkForDuplicateName(firstName)) { + if (checkForDuplicateName(firstName, client.getAccountId())) { approved_flag = "name_declined_in_use"; isDeclined = true; @@ -193,17 +203,16 @@ public class CharacterService implements INetworkDispatch { } int galaxyId = config.getInt("GALAXY_ID"); + Client client = core.getClient((Integer) session.getAttribute("connectionId")); try { - if (checkForDuplicateName(getfirstName(clientCreateCharacter.getName(), clientCreateCharacter.getRaceTemplate()))) { + if (checkForDuplicateName(getfirstName(clientCreateCharacter.getName(), clientCreateCharacter.getRaceTemplate()), client.getAccountId())) { return; } } catch (SQLException e2) { e2.printStackTrace(); } - Client client = core.getClient((Integer) session.getAttribute("connectionId")); - // TODO: Add starting location and items in a script String raceTemplate = clientCreateCharacter.getRaceTemplate(); // should set to some planet and starting location @@ -321,63 +330,72 @@ public class CharacterService implements INetworkDispatch { } - private boolean checkForDuplicateName(String firstName) throws SQLException + private boolean checkForDuplicateName(String firstName, long accountId) throws SQLException { firstName = firstName.replace("'", "''"); firstName = firstName.toLowerCase(); - PreparedStatement ps = databaseConnection.preparedStatement("SELECT id FROM characters WHERE LOWER(\"firstName\") ='" + firstName + "'"); + PreparedStatement ps = databaseConnection.preparedStatement("SELECT id FROM characters WHERE LOWER(\"firstName\")=?"); + ps.setString(1, firstName); + //System.out.println(ps.toString()); ResultSet resultSet = ps.executeQuery(); - - boolean bool = resultSet.next(); + + boolean isDuplicate = resultSet.next(); resultSet.getStatement().close(); - return bool; - } - + if (isDuplicate) { return true; } + //FIXME: this is a bit lazy... but it's only temporary :p + PreparedStatement psc = databaseConnection.preparedStatement("SELECT * FROM pg_tables WHERE \"tablename\"=?"); + psc.setString(1, "temp_reserved_char_names"); + ResultSet resultSetC = psc.executeQuery(); + boolean tableExists = resultSetC.next(); + resultSetC.getStatement().close(); + if (!tableExists) { return false; } + + PreparedStatement ps2 = databaseConnection.preparedStatement("SELECT \"accountId\" FROM temp_reserved_char_names WHERE \"accountId\"!=? AND LOWER(\"firstName\")=?"); + ps2.setLong(1, accountId); + ps2.setString(2, firstName); + ResultSet resultSet2 = ps2.executeQuery(); + boolean isReserved = resultSet2.next(); + resultSet2.getStatement().close(); + + return isReserved; + } + + private String getfirstName(String Name, String RaceTemplate) { - String[] splitName; - if (RaceTemplate != "object/creature/player/wookiee_male.iff" | RaceTemplate != "object/creature/player/wookiee_female.iff") + if (RaceTemplate.contains("/wookiee_") || + !Name.contains(" ")) { // wookies don't have lastNames - if (Name.contains(" ")) - { - splitName = Name.split(" ", 2); - return splitName[0]; - } - else - { return Name; - } - } - else - { - return Name; } + + return Name.split(" ", 2)[0]; + } private String getlastName(String Name, String RaceTemplate) { - String[] splitName; - if (RaceTemplate != "object/creature/player/wookiee_male.iff" && RaceTemplate != "object/creature/player/wookiee_female.iff") + if (RaceTemplate.contains("/wookiee_") || + !Name.contains(" ")) { // wookies don't have lastNames - if (Name.contains(" ")) - { - splitName = Name.split(" ", 2); - return splitName[1]; - } - else - { - return ""; - } - } - else - { return ""; } + + return Name.split(" ", 2)[1]; + } private String checkForReservedName(String firstName, String lastName) throws SQLException { + + PreparedStatement psc = databaseConnection.preparedStatement("SELECT * FROM pg_tables WHERE \"tablename\"=?"); + psc.setString(1, "reservednames"); + ResultSet rsc = psc.executeQuery(); + if (!rsc.next()) { + return null; + } + firstName = firstName.toLowerCase(); lastName = lastName.toLowerCase(); diff --git a/src/services/ConnectionService.java b/src/services/ConnectionService.java index b094b647..a2f291ed 100644 --- a/src/services/ConnectionService.java +++ b/src/services/ConnectionService.java @@ -69,6 +69,8 @@ public class ConnectionService implements INetworkDispatch { @Override public void handlePacket(IoSession session, IoBuffer data) throws Exception { + + System.out.println("xx"); data = data.order(ByteOrder.LITTLE_ENDIAN); ClientIdMsg clientIdMsg = new ClientIdMsg(); data.position(0); @@ -84,19 +86,22 @@ public class ConnectionService implements INetworkDispatch { PreparedStatement preparedStatement; try { - + preparedStatement = databaseConnection.preparedStatement("SELECT * FROM sessions WHERE key=?"); preparedStatement.setBytes(1, clientIdMsg.getSessionKey()); resultSet = preparedStatement.executeQuery(); if (resultSet.next()) { - client.setAccountId(resultSet.getInt("accountId")); + client.setAccountId(resultSet.getLong("accountId")); + client.setSessionKey(clientIdMsg.getSessionKey()); AccountFeatureBits accountFeatureBits = new AccountFeatureBits(); ClientPermissionsMessage clientPermissionsMessage = new ClientPermissionsMessage(); session.write(new HeartBeatMessage().serialize()); session.write(accountFeatureBits.serialize()); session.write(clientPermissionsMessage.serialize()); preparedStatement.close(); + + System.out.println("zyx"); } else { System.out.println("Cant get login session"); } @@ -105,8 +110,8 @@ public class ConnectionService implements INetworkDispatch { e.printStackTrace(); - } - + } + } diff --git a/src/services/LoginService.java b/src/services/LoginService.java index 92a3d42c..a4904be8 100644 --- a/src/services/LoginService.java +++ b/src/services/LoginService.java @@ -37,8 +37,11 @@ import org.apache.mina.core.session.IoSession; import engine.clients.Client; import engine.protocol.soe.Disconnect; import engine.resources.database.DatabaseConnection; +import engine.resources.service.ILoginProvider; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; +import engine.resources.service.LocalDbLoginProvider; +import engine.resources.service.VBLoginProvider; import protocol.swg.CharacterCreationDisabled; import protocol.swg.ClientUIErrorMessage; @@ -61,16 +64,22 @@ public class LoginService implements INetworkDispatch{ private int sessionKeyLength = 0; private NGECore core; - private DatabaseConnection databaseConnection; + private DatabaseConnection databaseConnection1; private DatabaseConnection databaseConnection2; private Random random; + private ILoginProvider LoginProvider; public LoginService(NGECore core) { this.core = core; this.sessionKeyLength = core.getConfig().getInt("LOGIN.SESSION_KEY_SIZE"); - this.databaseConnection = core.getDatabase1(); + this.databaseConnection1 = core.getDatabase1(); this.databaseConnection2 = core.getDatabase2(); this.random = new Random(); + if (databaseConnection2 == null) { + LoginProvider = new LocalDbLoginProvider(databaseConnection1); + } else { + LoginProvider = new VBLoginProvider(databaseConnection1, databaseConnection2); + } } public void insertTimedEventBindings(ScheduledExecutorService executor) { @@ -88,19 +97,24 @@ public class LoginService implements INetworkDispatch{ data.position(0); clientID.deserialize(data); - String err = ""; String user = clientID.getAccountName(); String pass = clientID.getPassword(); - int id = getAccountID(user); - if (id == -1) err = "Invalid Username"; - //String email = getAccountEmail(user); - //String encryptPass = getAccountPassword(user); + int id = LoginProvider.getAccountId(user, pass, session.getRemoteAddress().toString()); - if (err == "") - err = canUserLogin(user, /*email*/"", pass, /*encryptPass*/"", id, session.getRemoteAddress().toString()); - - if (err != "") { - System.out.println(user + " failed login because " + err); + if (id < 0) { + + String err = ""; + switch (id) { + case -1: + err = "Database error"; + break; + case -2: + err = "invalid user or password"; + break; + case -3: + err = "user is banned"; + break; + } ClientUIErrorMessage errMsg = new ClientUIErrorMessage("Invalid Login", err); session.write(errMsg.serialize()); Disconnect disconnect = new Disconnect((Integer)session.getAttribute("connectionId"), 6); @@ -167,7 +181,7 @@ public class LoginService implements INetworkDispatch{ PreparedStatement preparedStatement; - preparedStatement = databaseConnection.preparedStatement("DELETE FROM characters WHERE \"id\"=? AND \"galaxyId\"=? AND \"accountId\"=?"); + preparedStatement = databaseConnection1.preparedStatement("DELETE FROM characters WHERE \"id\"=? AND \"galaxyId\"=? AND \"accountId\"=?"); preparedStatement.setLong(1, packet.getcharId()); preparedStatement.setInt(2, packet.getgalaxyId()); preparedStatement.setInt(3, (int) client.getAccountId()); @@ -196,9 +210,9 @@ public class LoginService implements INetworkDispatch{ */ private void persistSession(Client client) throws SQLException { - String sessionValues = "?, " + client.getAccountId(); - PreparedStatement ps = databaseConnection.preparedStatement("INSERT INTO sessions (key, \"accountId\") VALUES (" + sessionValues + ")"); + PreparedStatement ps = databaseConnection1.preparedStatement("INSERT INTO sessions (\"key\", \"accountId\") VALUES (?, ?)"); ps.setBytes(1, client.getSessionKey()); + ps.setLong(2, client.getAccountId()); ps.executeUpdate(); ps.close(); @@ -226,7 +240,7 @@ public class LoginService implements INetworkDispatch{ PreparedStatement preparedStatement; try { - preparedStatement = databaseConnection.preparedStatement("SELECT * FROM characters WHERE \"accountId\"=" + id + ""); + preparedStatement = databaseConnection1.preparedStatement("SELECT * FROM characters WHERE \"accountId\"=" + id + ""); resultSet = preparedStatement.executeQuery(); while (resultSet.next() && !resultSet.isClosed()) { @@ -257,7 +271,7 @@ public class LoginService implements INetworkDispatch{ LoginEnumCluster servers = new LoginEnumCluster(9); PreparedStatement preparedStatement; try { - preparedStatement = databaseConnection.preparedStatement("SELECT * FROM galaxies"); + preparedStatement = databaseConnection1.preparedStatement("SELECT * FROM galaxies"); ResultSet resultSet = preparedStatement.executeQuery(); while (resultSet.next() && !resultSet.isClosed()) servers.addServer(resultSet.getInt("id"), resultSet.getString("name")); @@ -276,7 +290,7 @@ public class LoginService implements INetworkDispatch{ LoginClusterStatus clusterStatus = new LoginClusterStatus(); ResultSet resultSet; try { - PreparedStatement preparedStatement = databaseConnection.preparedStatement("SELECT * FROM \"connectionServers\""); + PreparedStatement preparedStatement = databaseConnection1.preparedStatement("SELECT * FROM \"connectionServers\""); resultSet = preparedStatement.executeQuery(); while (resultSet.next() && !resultSet.isClosed()) clusterStatus.addServer( @@ -294,111 +308,6 @@ public class LoginService implements INetworkDispatch{ return clusterStatus; } - /** - * Checks if account ID exists in game DB. - * @param id Account ID. - */ - private boolean checkIfAccountExistInGameDB(int id) { - try { - PreparedStatement preparedStatement = databaseConnection.preparedStatement("SELECT * FROM accounts WHERE id=?"); - preparedStatement.setInt(1, id); - ResultSet resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) { - return true; - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - - /** - * Saves forum account to game DB if the account does not exist in the game DB already. - * @param id Account ID. - * @param user Username - * @param email User's email - * @param pass Hashed password - */ - private void createAccountForGameDB(int id, String user, String email, String pass) { - try { - PreparedStatement ps = databaseConnection.preparedStatement("INSERT INTO accounts (id, \"user\", \"pass\", \"email\") VALUES (?, ?, ?, ?)"); - ps.setInt(1, id); - ps.setString(2, user); - ps.setString(3, pass); - ps.setString(4, email); - ps.executeUpdate(); - ps.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - - /** - * Checks if user is allowed to login. - * @param id Account ID. - * @param user Username - * @param email User's email - * @param pass User password - * @param encryptPass encrypted password - * @param ip Users IP address - */ - private String canUserLogin(String user, String email, String pass, String encryptPass, int id, String ip) { - /*if ((new PHPBB3Auth()).phpbb_check_hash(pass, encryptPass)) { - if(checkBanlistforUserAndIP(id, ip)) { - return "You cannot login to the ProjectSWG server while being banned from ProjectSWG services"; - } - return ""; - } else { - return "Invalid Password"; - }*/ - - try { - PreparedStatement ps = databaseConnection.preparedStatement("SELECT * FROM accounts WHERE id=" + id + " AND \"pass\"='" + pass + "'"); - ResultSet resultSet = ps.executeQuery(); - - if (resultSet.next()) { - - return ""; - - } - } catch (SQLException e) { - e.printStackTrace(); - } - - return "Invalid Password"; - - - } - /** - * Checks if User has a forum account or IP ban. - * @param id Account ID. - * @param ip User's IP address. - */ - private boolean checkBanlistforUserAndIP(int id, String ip) { - if (!ip.contains("/")) - return false; - String IP = ((ip.split("/", 2)[1]).split(", ", 2)[0]).split(":", 2)[0]; - try { - PreparedStatement preparedStatement = databaseConnection2.preparedStatement("SELECT ban_id FROM phpbb_banlist WHERE ban_ip=?"); - preparedStatement.setString(1, IP); - ResultSet resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) { - return true; - } else { - preparedStatement.close(); - preparedStatement = databaseConnection2.preparedStatement("SELECT ban_id FROM phpbb_banlist WHERE ban_userid=?"); - preparedStatement.setInt(1, id); - resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) { - return true; - } - } - } catch (SQLException e) { - e.printStackTrace(); - } - return false; - } - /** * Checks if User has correct client version. * @param version Client Version String @@ -407,61 +316,6 @@ public class LoginService implements INetworkDispatch{ System.out.println("Version Received: " + version); return true; } - - /** - * Gets Account ID from forum DB by username. - * @param user Username. - */ - private int getAccountID(String user) { - try { - PreparedStatement pStatement = databaseConnection.preparedStatement("SELECT id FROM accounts WHERE \"user\"='" + user + "'"); - ResultSet resultSet = pStatement.executeQuery(); - if (resultSet.next()) { - return resultSet.getInt("id"); - } - } catch (SQLException e) { - e.printStackTrace(); - }; - return -1; - } - - /** - * Gets Account Email from forum DB by username. - * @param user Username. - */ - private String getAccountEmail(String user) { - try { - PreparedStatement pStatement = databaseConnection2.preparedStatement("SELECT user_email FROM phpbb_users WHERE username=?"); - pStatement.setString(1, user); - ResultSet resultSet = pStatement.executeQuery(); - - if (resultSet.next()) { - return resultSet.getString("user_email"); - } - } catch (SQLException e) { - e.printStackTrace(); - }; - return ""; - } - - /** - * Gets hashed Account Password from forum DB by username. - * @param user Username. - */ - private String getAccountPassword(String user) { - try { - PreparedStatement pStatement = databaseConnection2.preparedStatement("SELECT user_password FROM phpbb_users WHERE username=?"); - pStatement.setString(1, user); - ResultSet resultSet = pStatement.executeQuery(); - - if (resultSet.next()) { - return resultSet.getString("user_password"); - } - pStatement.close(); - } catch (SQLException e) { - e.printStackTrace(); - }; - return ""; - } - + } + diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 146859a9..c19f25a8 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -284,7 +284,6 @@ public class ObjectService implements INetworkDispatch { System.out.println("!File Not Found:" + template.toString()); } catch (IOException e) { System.out.println("!IO error " + template.toString()); - e.printStackTrace(); } }