package client; import database.DatabaseConnection; import handling.channel.ChannelServer; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.regex.Pattern; import org.apache.log4j.Logger; import server.MapleItemInformationProvider; import tools.FileoutputUtil; import tools.Pair; import tools.Triple; public class MapleCharacterUtil { private static final Logger log = Logger.getLogger(MapleCharacterUtil.class); private static final Pattern namePattern = Pattern.compile("^(?!_)(?!.*?_$)[a-zA-Z0-9_一-龥]+$"); private static final Pattern petPattern = Pattern.compile("^(?!_)(?!.*?_$)[a-zA-Z0-9_一-龥]+$"); public static boolean canCreateChar(String name, boolean gm) { return (getIdByName(name) == -1) && (isEligibleCharName(name, gm)); } public static boolean canChangePetName(String name) { if ((name.getBytes().length < 4) || (name.getBytes().length > 12)) { return false; } return petPattern.matcher(name).matches(); } public static boolean isEligibleCharName(String name, boolean gm) { if (name.getBytes().length > 12) { return false; } if (gm) { return true; } if (name.getBytes().length < 4) { return false; } return namePattern.matcher(name).matches(); } public static String makeMapleReadable(String in) { String wui = in.replace('I', 'i'); wui = wui.replace('l', 'L'); wui = wui.replace("rn", "Rn"); wui = wui.replace("vv", "Vv"); wui = wui.replace("VV", "Vv"); return wui; } public static int getIdByName(String name) { Connection con = DatabaseConnection.getConnection(); try { int id; try (PreparedStatement ps = con.prepareStatement("SELECT id FROM characters WHERE name = ?")) { ps.setString(1, name); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return -1; } id = rs.getInt("id"); rs.close(); ps.close(); } return id; } catch (SQLException e) { log.error("error 'getIdByName' " + e); } return -1; } public static Pair<String, Integer> getNameById(int chrId, int world) { try { Connection con = DatabaseConnection.getConnection(); Pair id; try (PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE id = ? AND world = ?")) { ps.setInt(1, chrId); ps.setInt(2, world); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return null; } id = new Pair(rs.getString("name"), rs.getInt("accountid")); rs.close(); ps.close(); } return id; } catch (SQLException e) { log.error("error 'getInfoByName' " + e); } return null; } public static boolean PromptPoll(int accountid) { PreparedStatement ps = null; ResultSet rs = null; boolean prompt = false; try { ps = DatabaseConnection.getConnection().prepareStatement("SELECT * from game_poll_reply where AccountId = ?"); ps.setInt(1, accountid); rs = ps.executeQuery(); prompt = !rs.next(); ps.close(); } catch (SQLException e) { } finally { try { if (ps != null) { ps.close(); } if (rs != null) { rs.close(); } } catch (SQLException e) { } } return prompt; } public static boolean SetPoll(int accountid, int selection) { if (!PromptPoll(accountid)) { return false; } PreparedStatement ps = null; try { ps = DatabaseConnection.getConnection().prepareStatement("INSERT INTO game_poll_reply (AccountId, SelectAns) VALUES (?, ?)"); ps.setInt(1, accountid); ps.setInt(2, selection); ps.execute(); ps.close(); } catch (SQLException e) { } finally { try { if (ps != null) { ps.close(); } } catch (SQLException e) { } } return true; } public static int Change_SecondPassword(int accid, String password, String newpassword) { Connection con = DatabaseConnection.getConnection(); try { PreparedStatement ps = con.prepareStatement("SELECT * from accounts where id = ?"); ps.setInt(1, accid); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return -1; } String secondPassword = rs.getString("2ndpassword"); String salt2 = rs.getString("salt2"); if ((secondPassword != null) && (salt2 != null)) { secondPassword = LoginCrypto.rand_r(secondPassword); } else if ((secondPassword == null) && (salt2 == null)) { rs.close(); ps.close(); return 0; } if (!check_ifPasswordEquals(secondPassword, password, salt2)) { rs.close(); ps.close(); return 1; } rs.close(); ps.close(); String SHA1hashedsecond; try { SHA1hashedsecond = LoginCryptoLegacy.encodeSHA1(newpassword); } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { return -2; } ps = con.prepareStatement("UPDATE accounts set 2ndpassword = ?, salt2 = ? where id = ?"); ps.setString(1, SHA1hashedsecond); ps.setString(2, null); ps.setInt(3, accid); if (!ps.execute()) { ps.close(); return 2; } ps.close(); return -2; } catch (SQLException e) { log.error("修改二级密码发生错误" + e); } return -2; } private static boolean check_ifPasswordEquals(String passhash, String pwd, String salt) { if ((LoginCryptoLegacy.isLegacyPassword(passhash)) && (LoginCryptoLegacy.checkPassword(pwd, passhash))) { return true; } if ((salt == null) && (LoginCrypto.checkSha1Hash(passhash, pwd))) { return true; } return LoginCrypto.checkSaltedSha512Hash(passhash, pwd, salt); } public static Triple<Integer, Integer, Integer> getInfoByName(String name, int world) { try { Connection con = DatabaseConnection.getConnection(); Triple id; try (PreparedStatement ps = con.prepareStatement("SELECT * FROM characters WHERE name = ? AND world = ?")) { ps.setString(1, name); ps.setInt(2, world); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return null; } id = new Triple(rs.getInt("id"), rs.getInt("accountid"), rs.getInt("gender")); rs.close(); ps.close(); } return id; } catch (Exception e) { log.error("error 'getInfoByName' " + e); } return null; } public static void setNXCodeUsed(String name, String code) throws SQLException { Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("UPDATE nxcode SET `user` = ?, `valid` = 0, time = CURRENT_TIMESTAMP() WHERE code = ?")) { ps.setString(1, name); ps.setString(2, code); ps.execute(); ps.close(); } } /** * 玩家发给玩家的消息 * @param to * @param name * @param msg * @param fame */ public static void sendNote(String to, String name, String msg, int fame) { Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("INSERT INTO notes (`to`, `from`, `message`, `timestamp`, `gift`) VALUES (?, ?, ?, ?, ?)")) { ps.setString(1, to); ps.setString(2, name); ps.setString(3, msg); ps.setLong(4, System.currentTimeMillis()); ps.setInt(5, fame); ps.executeUpdate(); ps.close(); MapleCharacter receiver = ChannelServer.getCharacterByName(to); if (receiver != null) { receiver.showNote(); } } catch (SQLException e) { log.error("Unable to send note" + e); } } public static Triple<Boolean, Integer, Integer> getNXCodeInfo(String code) throws SQLException { Triple ret = null; Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("SELECT `valid`, `type`, `item` FROM nxcode WHERE code = ?")) { ps.setString(1, code); ResultSet rs = ps.executeQuery(); if (rs.next()) { ret = new Triple(rs.getInt("valid") > 0,rs.getInt("type"), rs.getInt("item")); } rs.close(); ps.close(); } return ret; } public static void addToItemSearch(int itemId) { MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance(); try { Connection con = DatabaseConnection.getConnection(); try (PreparedStatement ps = con.prepareStatement("SELECT * FROM itemsearch WHERE itemid = ?")) { ps.setInt(1, itemId); ResultSet rs = ps.executeQuery(); if (rs.next()) { int count = rs.getInt("count"); try (PreparedStatement psu = con.prepareStatement("UPDATE itemsearch SET count = ? WHERE itemid = ?")) { psu.setInt(1, count + 1); psu.setInt(2, itemId); psu.executeUpdate(); } } else { try (PreparedStatement psi = con.prepareStatement("INSERT INTO itemsearch (itemid, count, itemName) VALUES (?, ?, ?)")) { psi.setInt(1, itemId); psi.setInt(2, 1); psi.setString(3, ii.getName(itemId)); psi.executeUpdate(); } } rs.close(); ps.close(); } } catch (SQLException e) { FileoutputUtil.outputFileError(FileoutputUtil.SQL_Ex_Log, e); } } public static Pair<Integer, Integer> getCashByAccId(int AccId) { try { Connection con = DatabaseConnection.getConnection(); Pair id; try (PreparedStatement ps = con.prepareStatement("SELECT * FROM accounts WHERE id = ? ")) { ps.setInt(1, AccId); ResultSet rs = ps.executeQuery(); if (!rs.next()) { rs.close(); ps.close(); return null; } id = new Pair(rs.getInt("ACash"), rs.getInt("mPoints")); rs.close(); ps.close(); } return id; } catch (Exception e) { log.error("error 'getInfoByName' " + e); } return null; } }