mirror of
https://github.com/essentials/Essentials.git
synced 2025-10-04 01:51:58 +02:00
EssentialsUpdate WIP
This commit is contained in:
@@ -0,0 +1,601 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import f00f.net.irc.martyr.GenericAutoService;
|
||||
import f00f.net.irc.martyr.IRCConnection;
|
||||
import f00f.net.irc.martyr.InCommand;
|
||||
import f00f.net.irc.martyr.State;
|
||||
import f00f.net.irc.martyr.clientstate.Channel;
|
||||
import f00f.net.irc.martyr.clientstate.Member;
|
||||
import f00f.net.irc.martyr.commands.InviteCommand;
|
||||
import f00f.net.irc.martyr.commands.KickCommand;
|
||||
import f00f.net.irc.martyr.commands.MessageCommand;
|
||||
import f00f.net.irc.martyr.commands.NoticeCommand;
|
||||
import f00f.net.irc.martyr.commands.QuitCommand;
|
||||
import f00f.net.irc.martyr.commands.TopicCommand;
|
||||
import f00f.net.irc.martyr.errors.GenericJoinError;
|
||||
import f00f.net.irc.martyr.services.AutoJoin;
|
||||
import f00f.net.irc.martyr.services.AutoReconnect;
|
||||
import f00f.net.irc.martyr.services.AutoRegister;
|
||||
import f00f.net.irc.martyr.services.AutoResponder;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event.Priority;
|
||||
import org.bukkit.event.Event.Type;
|
||||
import org.bukkit.event.player.PlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerListener;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
|
||||
public class EssentialsHelp extends PlayerListener
|
||||
{
|
||||
private transient Player chatUser;
|
||||
private transient IRCConnection connection;
|
||||
private transient AutoReconnect autoReconnect;
|
||||
private transient boolean shouldQuit = false;
|
||||
private final transient Server server;
|
||||
private final transient Plugin plugin;
|
||||
private final static Charset UTF8 = Charset.forName("utf-8");
|
||||
|
||||
public EssentialsHelp(Plugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.server = plugin.getServer();
|
||||
}
|
||||
|
||||
public void registerEvents()
|
||||
{
|
||||
final PluginManager pluginManager = server.getPluginManager();
|
||||
pluginManager.registerEvent(Type.PLAYER_QUIT, this, Priority.Low, plugin);
|
||||
pluginManager.registerEvent(Type.PLAYER_CHAT, this, Priority.Low, plugin);
|
||||
}
|
||||
|
||||
public void onCommand(CommandSender sender)
|
||||
{
|
||||
if (sender instanceof Player && sender.hasPermission("essentials.helpchat"))
|
||||
{
|
||||
if (chatUser == null)
|
||||
{
|
||||
chatUser = (Player)sender;
|
||||
connection = null;
|
||||
sender.sendMessage("You will be connected to the Essentials Help Chat.");
|
||||
sender.sendMessage("All your chat messages will be forwarded to the channel. You can't chat with other players on your server while in help chat, but you can use commands.");
|
||||
sender.sendMessage("Please be patient, if noone is available, check back later.");
|
||||
sender.sendMessage("Type !help to get a list of all commands.");
|
||||
sender.sendMessage("Type !quit to leave the channel.");
|
||||
sender.sendMessage("Do you want to join the channel now? (yes/no)");
|
||||
}
|
||||
if (!chatUser.equals(sender))
|
||||
{
|
||||
sender.sendMessage("The player " + chatUser.getDisplayName() + " is already using the essentialshelp.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage("Please run the command as op from in game.");
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisable()
|
||||
{
|
||||
if (autoReconnect != null && connection != null)
|
||||
{
|
||||
autoReconnect.disable();
|
||||
shouldQuit = true;
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendChatMessage(final Player player, final String message)
|
||||
{
|
||||
final String messageCleaned = message.trim();
|
||||
if (messageCleaned.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (connection == null)
|
||||
{
|
||||
if (messageCleaned.equalsIgnoreCase("yes"))
|
||||
{
|
||||
player.sendMessage("Connecting...");
|
||||
connectToIRC(player);
|
||||
}
|
||||
if (messageCleaned.equalsIgnoreCase("no") || message.equalsIgnoreCase("!quit"))
|
||||
{
|
||||
chatUser = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
final String lowMessage = messageCleaned.toLowerCase();
|
||||
if (lowMessage.startsWith("!quit"))
|
||||
{
|
||||
chatUser = null;
|
||||
autoReconnect.disable();
|
||||
shouldQuit = true;
|
||||
connection.sendCommand(new QuitCommand("Connection closed by user."));
|
||||
player.sendMessage("Connection closed.");
|
||||
return;
|
||||
}
|
||||
if (!connection.getClientState().getChannels().hasMoreElements())
|
||||
{
|
||||
player.sendMessage("Not connected yet!");
|
||||
return;
|
||||
}
|
||||
if (lowMessage.startsWith("!list"))
|
||||
{
|
||||
final Enumeration members = ((Channel)connection.getClientState().getChannels().nextElement()).getMembers();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (members.hasMoreElements())
|
||||
{
|
||||
if (sb.length() > 0)
|
||||
{
|
||||
sb.append("§f, ");
|
||||
}
|
||||
final Member member = (Member)members.nextElement();
|
||||
if (member.hasOps() || member.hasVoice())
|
||||
{
|
||||
sb.append("§6");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("§7");
|
||||
}
|
||||
sb.append(member.getNick());
|
||||
}
|
||||
player.sendMessage(sb.toString());
|
||||
return;
|
||||
}
|
||||
if (lowMessage.startsWith("!help"))
|
||||
{
|
||||
player.sendMessage("Commands: (Note: Files send to the chat will be public viewable.)");
|
||||
player.sendMessage("!errors - Send the last server errors to the chat.");
|
||||
player.sendMessage("!startup - Send the last startup messages to the chat.");
|
||||
player.sendMessage("!config - Sends your Essentials config to the chat.");
|
||||
player.sendMessage("!list - List all players in chat.");
|
||||
player.sendMessage("!quit - Leave chat.");
|
||||
return;
|
||||
}
|
||||
if (lowMessage.startsWith("!errors"))
|
||||
{
|
||||
sendErrors();
|
||||
return;
|
||||
}
|
||||
if (lowMessage.startsWith("!startup"))
|
||||
{
|
||||
sendStartup();
|
||||
return;
|
||||
}
|
||||
if (lowMessage.startsWith("!config"))
|
||||
{
|
||||
sendConfig();
|
||||
return;
|
||||
}
|
||||
final Channel channel = (Channel)connection.getClientState().getChannels().nextElement();
|
||||
connection.sendCommand(new MessageCommand(channel.getName(), messageCleaned));
|
||||
chatUser.sendMessage("§6" + connection.getClientState().getNick().getNick() + ": §7" + messageCleaned);
|
||||
}
|
||||
}
|
||||
|
||||
private void connectToIRC(final Player player)
|
||||
{
|
||||
connection = new IRCConnection();
|
||||
// Required services
|
||||
new AutoResponder(connection);
|
||||
int versionNumber = 0;
|
||||
final StringBuilder nameBuilder = new StringBuilder();
|
||||
nameBuilder.append(player.getName());
|
||||
|
||||
final Matcher versionMatch = Pattern.compile("git-Bukkit-([0-9]+).([0-9]+).([0-9]+)-[0-9]+-[0-9a-z]+-b([0-9]+)jnks.*").matcher(server.getVersion());
|
||||
if (versionMatch.matches())
|
||||
{
|
||||
nameBuilder.append(" CB");
|
||||
nameBuilder.append(versionMatch.group(4));
|
||||
}
|
||||
|
||||
final Plugin essentials = server.getPluginManager().getPlugin("Essentials");
|
||||
if (essentials != null)
|
||||
{
|
||||
nameBuilder.append(" ESS");
|
||||
nameBuilder.append(essentials.getDescription().getVersion());
|
||||
}
|
||||
|
||||
final Plugin groupManager = server.getPluginManager().getPlugin("GroupManager");
|
||||
if (groupManager != null)
|
||||
{
|
||||
nameBuilder.append(" GM");
|
||||
if (!groupManager.isEnabled())
|
||||
{
|
||||
nameBuilder.append('!');
|
||||
}
|
||||
}
|
||||
|
||||
final Plugin pex = server.getPluginManager().getPlugin("PermissionsEx");
|
||||
if (pex != null)
|
||||
{
|
||||
nameBuilder.append(" PEX");
|
||||
if (!pex.isEnabled())
|
||||
{
|
||||
nameBuilder.append('!');
|
||||
}
|
||||
nameBuilder.append(pex.getDescription().getVersion());
|
||||
}
|
||||
|
||||
final Plugin pb = server.getPluginManager().getPlugin("PermissionsBukkit");
|
||||
if (pb != null)
|
||||
{
|
||||
nameBuilder.append(" PB");
|
||||
if (!pb.isEnabled())
|
||||
{
|
||||
nameBuilder.append('!');
|
||||
}
|
||||
nameBuilder.append(pb.getDescription().getVersion());
|
||||
}
|
||||
|
||||
final Plugin bp = server.getPluginManager().getPlugin("bPermissions");
|
||||
if (bp != null)
|
||||
{
|
||||
nameBuilder.append(" BP");
|
||||
if (!bp.isEnabled())
|
||||
{
|
||||
nameBuilder.append('!');
|
||||
}
|
||||
nameBuilder.append(bp.getDescription().getVersion());
|
||||
}
|
||||
|
||||
final Plugin perm = server.getPluginManager().getPlugin("Permissions");
|
||||
if (perm != null)
|
||||
{
|
||||
nameBuilder.append(" P");
|
||||
if (!perm.isEnabled())
|
||||
{
|
||||
nameBuilder.append('!');
|
||||
}
|
||||
nameBuilder.append(perm.getDescription().getVersion());
|
||||
}
|
||||
|
||||
new AutoRegister(connection, "Ess_" + player.getName(), "esshelp", nameBuilder.toString());
|
||||
|
||||
autoReconnect = new AutoReconnect(connection);
|
||||
new KickAutoJoin(connection, "#essentials");
|
||||
|
||||
new IRCListener(connection);
|
||||
autoReconnect.go("irc.esper.net", 6667);
|
||||
}
|
||||
|
||||
private void handleIRCmessage(final String nick, final String message)
|
||||
{
|
||||
|
||||
if (chatUser != null)
|
||||
{
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append("§6");
|
||||
sb.append(nick);
|
||||
sb.append(": §7");
|
||||
final String coloredmessage = message.replace("\u000300", "§f").replace("\u000301", "§0").replace("\u000302", "§1").replace("\u000303", "§2").replace("\u000304", "§c").replace("\u000305", "§4").replace("\u000306", "§5").replace("\u000307", "§6").replace("\u000308", "§e").replace("\u000309", "§a").replace("\u00030", "§f").replace("\u000310", "§b").replace("\u000311", "§f").replace("\u000312", "§9").replace("\u000313", "§d").replace("\u000314", "§8").replace("\u000315", "§7").replace("\u00031", "§0").replace("\u00032", "§1").replace("\u00033", "§2").replace("\u00034", "§c").replace("\u00035", "§4").replace("\u00036", "§5").replace("\u00037", "§6").replace("\u00038", "§e").replace("\u00039", "§a").replace("\u0003", "§7");
|
||||
sb.append(coloredmessage);
|
||||
chatUser.sendMessage(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void sendErrors()
|
||||
{
|
||||
BufferedReader page = null;
|
||||
try
|
||||
{
|
||||
File bukkitFolder = plugin.getDataFolder().getAbsoluteFile().getParentFile().getParentFile();
|
||||
if (bukkitFolder == null || !bukkitFolder.exists())
|
||||
{
|
||||
chatUser.sendMessage("Bukkit folder not found.");
|
||||
return;
|
||||
}
|
||||
File logFile = new File(bukkitFolder, "server.log");
|
||||
if (!logFile.exists())
|
||||
{
|
||||
chatUser.sendMessage("Server log not found.");
|
||||
return;
|
||||
}
|
||||
FileInputStream fis = new FileInputStream(logFile);
|
||||
if (logFile.length() > 1000000)
|
||||
{
|
||||
fis.skip(logFile.length()-1000000);
|
||||
}
|
||||
page = new BufferedReader(new InputStreamReader(fis));
|
||||
final StringBuilder input = new StringBuilder();
|
||||
String line;
|
||||
Pattern pattern = Pattern.compile("^[0-9 :-]+\\[INFO\\].*");
|
||||
while ((line = page.readLine()) != null)
|
||||
{
|
||||
if (!pattern.matcher(line).matches()) {
|
||||
input.append(line).append("\n");
|
||||
}
|
||||
}
|
||||
if (input.length()>10000) {
|
||||
input.delete(0, input.length()-10000);
|
||||
}
|
||||
final PastieUpload pastie = new PastieUpload();
|
||||
final String url = pastie.send(input.toString());
|
||||
final Channel channel = (Channel)connection.getClientState().getChannels().nextElement();
|
||||
String message = "Errors: " + url;
|
||||
chatUser.sendMessage("§6" + connection.getClientState().getNick().getNick() + ": §7" + message);
|
||||
connection.sendCommand(new MessageCommand(channel.getName(), message));
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.SEVERE, null, ex);
|
||||
chatUser.sendMessage(ex.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (page != null)
|
||||
{
|
||||
page.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendStartup()
|
||||
{
|
||||
BufferedReader page = null;
|
||||
try
|
||||
{
|
||||
File bukkitFolder = plugin.getDataFolder().getAbsoluteFile().getParentFile().getParentFile();
|
||||
if (bukkitFolder == null || !bukkitFolder.exists())
|
||||
{
|
||||
chatUser.sendMessage("Bukkit folder not found.");
|
||||
return;
|
||||
}
|
||||
File logFile = new File(bukkitFolder, "server.log");
|
||||
if (!logFile.exists())
|
||||
{
|
||||
chatUser.sendMessage("Server log not found.");
|
||||
return;
|
||||
}
|
||||
FileInputStream fis = new FileInputStream(logFile);
|
||||
if (logFile.length() > 1000000)
|
||||
{
|
||||
fis.skip(logFile.length()-1000000);
|
||||
}
|
||||
page = new BufferedReader(new InputStreamReader(fis));
|
||||
final StringBuilder input = new StringBuilder();
|
||||
String line;
|
||||
Pattern patternStart = Pattern.compile("^[0-9 :-]+\\[INFO\\] Starting minecraft server version.*");
|
||||
Pattern patternEnd = Pattern.compile("^[0-9 :-]+\\[INFO\\] Done \\([0-9.,]+s\\)! For help, type \"help\".*");
|
||||
boolean log = false;
|
||||
while ((line = page.readLine()) != null)
|
||||
{
|
||||
if (patternStart.matcher(line).matches()) {
|
||||
if (input.length() > 0) {
|
||||
input.delete(0, input.length());
|
||||
}
|
||||
log = true;
|
||||
}
|
||||
if (log) {
|
||||
input.append(line).append("\n");
|
||||
}
|
||||
if (patternEnd.matcher(line).matches()) {
|
||||
log = false;
|
||||
}
|
||||
}
|
||||
if (input.length()>10000) {
|
||||
input.delete(0, input.length()-10000);
|
||||
}
|
||||
final PastieUpload pastie = new PastieUpload();
|
||||
final String url = pastie.send(input.toString());
|
||||
final Channel channel = (Channel)connection.getClientState().getChannels().nextElement();
|
||||
String message = "Startup: " + url;
|
||||
chatUser.sendMessage("§6" + connection.getClientState().getNick().getNick() + ": §7" + message);
|
||||
connection.sendCommand(new MessageCommand(channel.getName(), message));
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.SEVERE, null, ex);
|
||||
chatUser.sendMessage(ex.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (page != null)
|
||||
{
|
||||
page.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendConfig()
|
||||
{
|
||||
BufferedReader page = null;
|
||||
try
|
||||
{
|
||||
File configFolder = new File(plugin.getDataFolder().getParentFile(), "Essentials");
|
||||
if (!configFolder.exists())
|
||||
{
|
||||
chatUser.sendMessage("Essentials plugin folder not found.");
|
||||
return;
|
||||
}
|
||||
File configFile = new File(configFolder, "config.yml");
|
||||
if (!configFile.exists())
|
||||
{
|
||||
chatUser.sendMessage("Essentials config file not found.");
|
||||
return;
|
||||
}
|
||||
page = new BufferedReader(new InputStreamReader(new FileInputStream(configFile), UTF8));
|
||||
final StringBuilder input = new StringBuilder();
|
||||
String line;
|
||||
while ((line = page.readLine()) != null)
|
||||
{
|
||||
input.append(line).append("\n");
|
||||
}
|
||||
final PastieUpload pastie = new PastieUpload();
|
||||
final String url = pastie.send(input.toString());
|
||||
final Channel channel = (Channel)connection.getClientState().getChannels().nextElement();
|
||||
String message = "Essentials config.yml: " + url;
|
||||
chatUser.sendMessage("§6" + connection.getClientState().getNick().getNick() + ": §7" + message);
|
||||
connection.sendCommand(new MessageCommand(channel.getName(), message));
|
||||
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.SEVERE, null, ex);
|
||||
chatUser.sendMessage(ex.getMessage());
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (page != null)
|
||||
{
|
||||
page.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Logger.getLogger(EssentialsHelp.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerChat(PlayerChatEvent event)
|
||||
{
|
||||
if (event.getPlayer() == chatUser)
|
||||
{
|
||||
sendChatMessage(event.getPlayer(), event.getMessage());
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerQuit(PlayerQuitEvent event)
|
||||
{
|
||||
chatUser = null;
|
||||
if (autoReconnect != null)
|
||||
{
|
||||
autoReconnect.disable();
|
||||
}
|
||||
shouldQuit = true;
|
||||
if (connection != null)
|
||||
{
|
||||
connection.sendCommand(new QuitCommand("Connection closed by user."));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
class KickAutoJoin extends AutoJoin
|
||||
{
|
||||
private String channel;
|
||||
|
||||
public KickAutoJoin(IRCConnection connection, String channel)
|
||||
{
|
||||
super(connection, channel);
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCommand(InCommand command_o)
|
||||
{
|
||||
if (command_o instanceof KickCommand)
|
||||
{
|
||||
final KickCommand kickCommand = (KickCommand)command_o;
|
||||
|
||||
if (kickCommand.kickedUs(getConnection().getClientState()))
|
||||
{
|
||||
if (Channel.areEqual(kickCommand.getChannel(), channel))
|
||||
{
|
||||
chatUser.sendMessage("You have been kicked from the channel: " + kickCommand.getComment());
|
||||
chatUser = null;
|
||||
autoReconnect.disable();
|
||||
shouldQuit = true;
|
||||
connection.sendCommand(new QuitCommand("Connection closed by user."));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (command_o instanceof GenericJoinError)
|
||||
{
|
||||
GenericJoinError joinErr = (GenericJoinError)command_o;
|
||||
|
||||
if (Channel.areEqual(joinErr.getChannel(), channel))
|
||||
{
|
||||
scheduleJoin();
|
||||
}
|
||||
}
|
||||
else if (command_o instanceof InviteCommand)
|
||||
{
|
||||
InviteCommand invite = (InviteCommand)command_o;
|
||||
if (!getConnection().getClientState().isOnChannel(invite.getChannel()))
|
||||
{
|
||||
performJoin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class IRCListener extends GenericAutoService
|
||||
{
|
||||
public IRCListener(final IRCConnection connection)
|
||||
{
|
||||
super(connection);
|
||||
enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateState(final State state)
|
||||
{
|
||||
if (state == State.UNCONNECTED && shouldQuit)
|
||||
{
|
||||
connection = null;
|
||||
shouldQuit = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateCommand(final InCommand command)
|
||||
{
|
||||
if (command instanceof MessageCommand)
|
||||
{
|
||||
final MessageCommand msg = (MessageCommand)command;
|
||||
EssentialsHelp.this.handleIRCmessage(msg.getSource().getNick(), msg.getMessage());
|
||||
}
|
||||
if (command instanceof TopicCommand)
|
||||
{
|
||||
final TopicCommand msg = (TopicCommand)command;
|
||||
EssentialsHelp.this.handleIRCmessage(msg.getChannel(), msg.getTopic());
|
||||
}
|
||||
if (command instanceof NoticeCommand)
|
||||
{
|
||||
final NoticeCommand msg = (NoticeCommand)command;
|
||||
EssentialsHelp.this.handleIRCmessage(msg.getFrom().getNick(), msg.getNotice());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import com.earth2me.essentials.update.UpdateCheck.CheckResult;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
|
||||
public class EssentialsUpdate extends JavaPlugin
|
||||
{
|
||||
private transient EssentialsHelp essentialsHelp;
|
||||
private transient UpdateProcess updateProcess;
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
if (!getDataFolder().exists() && !getDataFolder().mkdirs() ) {
|
||||
Bukkit.getLogger().severe("Could not create data folder:"+getDataFolder().getPath());
|
||||
}
|
||||
essentialsHelp = new EssentialsHelp(this);
|
||||
essentialsHelp.registerEvents();
|
||||
|
||||
final UpdateCheck updateCheck = new UpdateCheck(this);
|
||||
updateProcess = new UpdateProcess(this, updateCheck);
|
||||
updateProcess.registerEvents();
|
||||
|
||||
Bukkit.getLogger().info("EssentialsUpdate " + getDescription().getVersion() + " loaded.");
|
||||
|
||||
if (updateCheck.isEssentialsInstalled())
|
||||
{
|
||||
updateCheck.checkForUpdates();
|
||||
final Version myVersion = new Version(getDescription().getVersion());
|
||||
if (updateCheck.getResult() == CheckResult.NEW_ESS && myVersion.equals(updateCheck.getNewVersion()))
|
||||
{
|
||||
Bukkit.getLogger().info("Versions of EssentialsUpdate and Essentials do not match. Starting automatic update.");
|
||||
updateProcess.doAutomaticUpdate();
|
||||
}
|
||||
updateCheck.scheduleUpdateTask();
|
||||
}
|
||||
else
|
||||
{
|
||||
Bukkit.getLogger().info("Essentials is ready for installation. Join the game and follow the instructions.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable()
|
||||
{
|
||||
essentialsHelp.onDisable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(final CommandSender sender, final Command command, final String label, final String[] args)
|
||||
{
|
||||
if (command.getName().equalsIgnoreCase("essentialsupdate"))
|
||||
{
|
||||
updateProcess.onCommand(sender);
|
||||
}
|
||||
if (command.getName().equalsIgnoreCase("essentialshelp"))
|
||||
{
|
||||
essentialsHelp.onCommand(sender);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
112
EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java
Normal file
112
EssentialsUpdate/src/com/earth2me/essentials/update/GetFile.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class GetFile
|
||||
{
|
||||
private transient URLConnection connection;
|
||||
private transient MessageDigest digest;
|
||||
|
||||
public GetFile(final String urlString) throws MalformedURLException, IOException
|
||||
{
|
||||
final URL url = new URL(urlString);
|
||||
this.connection = url.openConnection();
|
||||
this.connection.setConnectTimeout(1000);
|
||||
this.connection.setReadTimeout(5000);
|
||||
this.connection.setUseCaches(false);
|
||||
this.connection.connect();
|
||||
final int respCode = ((HttpURLConnection)this.connection).getResponseCode();
|
||||
if (respCode >= 300 && respCode < 400 && this.connection.getHeaderField("Location") != null)
|
||||
{
|
||||
connection.getInputStream().close();
|
||||
final URL redirect = new URL(this.connection.getHeaderField("Location"));
|
||||
this.connection = redirect.openConnection();
|
||||
this.connection.setConnectTimeout(1000);
|
||||
this.connection.setReadTimeout(5000);
|
||||
this.connection.setUseCaches(false);
|
||||
this.connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveTo(final File file) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
saveTo(file, null);
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex)
|
||||
{
|
||||
// Ignore because the code is never called
|
||||
}
|
||||
}
|
||||
|
||||
public void saveTo(final File file, final String key) throws IOException, NoSuchAlgorithmException
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
digest = MessageDigest.getInstance("SHA256");
|
||||
}
|
||||
final byte[] buffer = new byte[1024 * 8];
|
||||
boolean brokenFile = false;
|
||||
final BufferedInputStream input = new BufferedInputStream(connection.getInputStream());
|
||||
try
|
||||
{
|
||||
final BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
|
||||
try
|
||||
{
|
||||
int length;
|
||||
do
|
||||
{
|
||||
length = input.read(buffer);
|
||||
if (length >= 0)
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
digest.update(buffer, 0, length);
|
||||
}
|
||||
output.write(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
while (length >= 0);
|
||||
if (key != null)
|
||||
{
|
||||
final byte[] checksum = digest.digest();
|
||||
final String checksumString = new BigInteger(checksum).toString(36);
|
||||
if (!checksumString.equals(key))
|
||||
{
|
||||
brokenFile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
output.close();
|
||||
}
|
||||
if (brokenFile && !file.delete())
|
||||
{
|
||||
Logger.getLogger("Minecraft").severe("Could not delete file " + file.getPath());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
if (brokenFile)
|
||||
{
|
||||
throw new IOException("Checksum check failed.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
|
||||
|
||||
public class ModuleInfo
|
||||
{
|
||||
private final transient String url;
|
||||
private final transient String version;
|
||||
private final transient String hash;
|
||||
|
||||
public ModuleInfo(final Configuration updateConfig, final String path)
|
||||
{
|
||||
url = updateConfig.getString(path + ".url", null);
|
||||
version = updateConfig.getString(path + ".version", null);
|
||||
hash = updateConfig.getString(path + ".hash", null);
|
||||
}
|
||||
|
||||
public URL getUrl() throws MalformedURLException
|
||||
{
|
||||
return new URL(url);
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getHash()
|
||||
{
|
||||
return hash;
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class PastieUpload
|
||||
{
|
||||
private final transient PostToUrl connection;
|
||||
|
||||
public PastieUpload() throws MalformedURLException
|
||||
{
|
||||
connection = new PostToUrl(new URL("http://pastie.org/pastes"));
|
||||
}
|
||||
|
||||
public String send(final String data) throws IOException
|
||||
{
|
||||
final Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("paste[parser_id]", "19");
|
||||
map.put("paste[authorization]", "burger");
|
||||
map.put("paste[body]", data);
|
||||
map.put("paste[restricted]", "1");
|
||||
final String html = connection.send(map);
|
||||
final Matcher matcher = Pattern.compile("(?s).*\\?key=([a-z0-9]+).*").matcher(html);
|
||||
if (matcher.matches())
|
||||
{
|
||||
final String key = matcher.group(1);
|
||||
return "http://pastie.org/private/" + key;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Failed to upload to pastie.org");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class PostToUrl
|
||||
{
|
||||
private final transient URL url;
|
||||
private final transient String boundary;
|
||||
private final transient Random random = new Random();
|
||||
private final static String CRLF = "\r\n";
|
||||
private final static Charset UTF8 = Charset.forName("utf-8");
|
||||
|
||||
public PostToUrl(final URL url)
|
||||
{
|
||||
this.url = url;
|
||||
final byte[] bytes = new byte[32];
|
||||
random.nextBytes(bytes);
|
||||
this.boundary = "----------" + new BigInteger(bytes).toString(Character.MAX_RADIX) + "_$";
|
||||
}
|
||||
|
||||
public String send(final Map<String, Object> data) throws IOException
|
||||
{
|
||||
final URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("content-type", "multipart/form-data; boundary=" + boundary);
|
||||
final StringBuilder dataBuilder = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : data.entrySet())
|
||||
{
|
||||
if (entry.getValue() instanceof String)
|
||||
{
|
||||
dataBuilder.append("--").append(boundary).append(CRLF);
|
||||
dataBuilder.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append('"').append(CRLF);
|
||||
dataBuilder.append(CRLF);
|
||||
dataBuilder.append(entry.getValue()).append(CRLF);
|
||||
}
|
||||
// TODO: Add support for file upload
|
||||
}
|
||||
dataBuilder.append("--").append(boundary).append("--").append(CRLF);
|
||||
dataBuilder.append(CRLF);
|
||||
connection.setDoOutput(true);
|
||||
final byte[] message = dataBuilder.toString().getBytes(UTF8);
|
||||
connection.setRequestProperty("content-length", Integer.toString(message.length));
|
||||
connection.connect();
|
||||
final OutputStream stream = connection.getOutputStream();
|
||||
stream.write(message);
|
||||
stream.close();
|
||||
final BufferedReader page = new BufferedReader(new InputStreamReader(connection.getInputStream(), UTF8));
|
||||
final StringBuilder input = new StringBuilder();
|
||||
String line;
|
||||
while ((line = page.readLine()) != null)
|
||||
{
|
||||
input.append(line).append("\n");
|
||||
}
|
||||
page.close();
|
||||
return input.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,203 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
|
||||
public class UpdateCheck
|
||||
{
|
||||
private transient CheckResult result = CheckResult.UNKNOWN;
|
||||
private transient Version currentVersion;
|
||||
private transient Version newVersion = null;
|
||||
private transient int bukkitResult = 0;
|
||||
private transient UpdateFile updateFile;
|
||||
private final static int CHECK_INTERVAL = 20 * 60 * 60 * 6;
|
||||
private final transient Plugin plugin;
|
||||
private transient boolean essentialsInstalled;
|
||||
|
||||
public UpdateCheck(Plugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
updateFile = new UpdateFile(plugin);
|
||||
checkForEssentials();
|
||||
}
|
||||
|
||||
private void checkForEssentials()
|
||||
{
|
||||
PluginManager pm = plugin.getServer().getPluginManager();
|
||||
Plugin essentials = pm.getPlugin("Essentials");
|
||||
if (essentials == null)
|
||||
{
|
||||
essentialsInstalled = false;
|
||||
if (new File(plugin.getDataFolder().getParentFile(), "Essentials.jar").exists())
|
||||
{
|
||||
Bukkit.getLogger().severe("Essentials.jar found, but not recognized by Bukkit. Broken download?");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
essentialsInstalled = true;
|
||||
currentVersion = new Version(essentials.getDescription().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public void scheduleUpdateTask()
|
||||
{
|
||||
plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(plugin, new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
updateFile = new UpdateFile(plugin);
|
||||
checkForUpdates();
|
||||
}
|
||||
}, CHECK_INTERVAL, CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
public boolean isEssentialsInstalled()
|
||||
{
|
||||
return essentialsInstalled;
|
||||
}
|
||||
|
||||
public CheckResult getResult()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
int getNewBukkitVersion()
|
||||
{
|
||||
return bukkitResult;
|
||||
}
|
||||
|
||||
VersionInfo getNewVersionInfo()
|
||||
{
|
||||
return updateFile.getVersions().get(newVersion);
|
||||
}
|
||||
|
||||
public enum CheckResult
|
||||
{
|
||||
NEW_ESS, NEW_ESS_BUKKIT, NEW_BUKKIT, OK, UNKNOWN
|
||||
}
|
||||
|
||||
public void checkForUpdates()
|
||||
{
|
||||
if (currentVersion == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
final Map<Version, VersionInfo> versions = updateFile.getVersions();
|
||||
final int bukkitVersion = getBukkitVersion();
|
||||
Version higher = null;
|
||||
Version found = null;
|
||||
Version lower = null;
|
||||
int bukkitHigher = 0;
|
||||
int bukkitLower = 0;
|
||||
for (Entry<Version, VersionInfo> entry : versions.entrySet())
|
||||
{
|
||||
final int minBukkit = entry.getValue().getMinBukkit();
|
||||
final int maxBukkit = entry.getValue().getMaxBukkit();
|
||||
if (minBukkit == 0 || maxBukkit == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (bukkitVersion <= maxBukkit)
|
||||
{
|
||||
if (bukkitVersion < minBukkit)
|
||||
{
|
||||
if (higher == null || higher.compareTo(entry.getKey()) < 0)
|
||||
{
|
||||
|
||||
higher = entry.getKey();
|
||||
bukkitHigher = minBukkit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (found == null || found.compareTo(entry.getKey()) < 0)
|
||||
{
|
||||
found = entry.getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lower == null || lower.compareTo(entry.getKey()) < 0)
|
||||
{
|
||||
lower = entry.getKey();
|
||||
bukkitLower = minBukkit;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found != null)
|
||||
{
|
||||
if (found.compareTo(currentVersion) > 0)
|
||||
{
|
||||
result = CheckResult.NEW_ESS;
|
||||
newVersion = found;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CheckResult.OK;
|
||||
}
|
||||
}
|
||||
else if (higher != null)
|
||||
{
|
||||
if (higher.compareTo(currentVersion) > 0)
|
||||
{
|
||||
newVersion = higher;
|
||||
result = CheckResult.NEW_ESS_BUKKIT;
|
||||
bukkitResult = bukkitHigher;
|
||||
}
|
||||
else if (higher.compareTo(currentVersion) < 0)
|
||||
{
|
||||
result = CheckResult.UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CheckResult.NEW_BUKKIT;
|
||||
bukkitResult = bukkitHigher;
|
||||
}
|
||||
}
|
||||
else if (lower != null)
|
||||
{
|
||||
if (lower.compareTo(currentVersion) > 0)
|
||||
{
|
||||
result = CheckResult.NEW_ESS_BUKKIT;
|
||||
newVersion = lower;
|
||||
bukkitResult = bukkitLower;
|
||||
}
|
||||
else if (lower.compareTo(currentVersion) < 0)
|
||||
{
|
||||
result = CheckResult.UNKNOWN;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CheckResult.NEW_BUKKIT;
|
||||
bukkitResult = bukkitLower;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getBukkitVersion()
|
||||
{
|
||||
final Matcher versionMatch = Pattern.compile("git-Bukkit-([0-9]+).([0-9]+).([0-9]+)-[0-9]+-[0-9a-z]+-b([0-9]+)jnks.*").matcher(plugin.getServer().getVersion());
|
||||
if (versionMatch.matches())
|
||||
{
|
||||
return Integer.parseInt(versionMatch.group(4));
|
||||
}
|
||||
throw new NumberFormatException("Bukkit Version changed!");
|
||||
}
|
||||
|
||||
public Version getNewVersion()
|
||||
{
|
||||
return newVersion;
|
||||
}
|
||||
}
|
@@ -0,0 +1,204 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
|
||||
public class UpdateFile
|
||||
{
|
||||
private final static Logger LOGGER = Logger.getLogger("Minecraft");
|
||||
private final static String UPDATE_URL = "http://goo.gl/67jev";
|
||||
private final static BigInteger PUBLIC_KEY = new BigInteger("5ha6a2d4qdy17ttkg8evh74sl5a87djojwenu12k1lvy8ui6003e6l06rntczpoh99mhc3txj8mqlxw111oyy9yl7s7qpyluyzix3j1odxrxx4u52gxvyu6qiteapczkzvi7rxgeqsozz7b19rdx73a7quo9ybwpz1cr82r7x5k0pg2a73pjjsv2j1awr13azo7klrcxp9y5xxwf5qv1s3tw4zqftli18u0ek5qkbzfbgk1v5n2f11pkwwk6p0mibrn26wnjbv11vyiqgu95o7busmt6vf5q7grpcenl637w83mbin56s3asj1131b2mscj9xep3cbj7la9tgsxl5bj87vzy8sk2d34kzwqdqgh9nry43nqqus12l1stmiv184r8r3jcy8w43e8h1u1mzklldb5eytkuhayqik8l3ns04hwt8sgacvw534be8sx26qrn5s1", 36);
|
||||
private final transient File file;
|
||||
private transient YamlConfiguration updateConfig;
|
||||
private final transient Plugin plugin;
|
||||
private final transient TreeMap<Version, VersionInfo> versions = new TreeMap<Version, VersionInfo>();
|
||||
|
||||
public UpdateFile(final Plugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
final long lastUpdate = Long.parseLong(plugin.getConfig().getString("lastupdate", "0"));
|
||||
file = new File(plugin.getDataFolder(), "update.yml");
|
||||
if (lastUpdate < System.currentTimeMillis() - 1000 * 60 * 60 * 6 || !file.exists())
|
||||
{
|
||||
if (file.exists() && !file.delete())
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Could not delete file update.yml!");
|
||||
return;
|
||||
}
|
||||
if (!downloadFile() || !checkFile())
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Could not download and verify file update.yml!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
readVersions();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Could not load update.yml!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean downloadFile()
|
||||
{
|
||||
GetFile getFile;
|
||||
try
|
||||
{
|
||||
getFile = new GetFile(UPDATE_URL);
|
||||
getFile.saveTo(file);
|
||||
plugin.getConfig().set("lastupdate", System.currentTimeMillis());
|
||||
plugin.getConfig().save(new File(plugin.getDataFolder(),"config.yml"));
|
||||
return true;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, "Error while downloading update.yml", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkFile()
|
||||
{
|
||||
BufferedInputStream bis = null;
|
||||
try
|
||||
{
|
||||
bis = new BufferedInputStream(new FileInputStream(file));
|
||||
if (bis.read() != '#')
|
||||
{
|
||||
throw new IOException("File has to start with #");
|
||||
}
|
||||
final StringBuilder length = new StringBuilder();
|
||||
final StringBuilder signature = new StringBuilder();
|
||||
boolean isSignature = false;
|
||||
do
|
||||
{
|
||||
final int cur = bis.read();
|
||||
if (cur == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (cur == ':')
|
||||
{
|
||||
isSignature = true;
|
||||
}
|
||||
else if (cur == '\n')
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if ((cur >= '0' && cur <= '9')
|
||||
|| (cur >= 'a' && cur <= 'z'))
|
||||
{
|
||||
if (isSignature)
|
||||
{
|
||||
signature.append((char)cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
length.append((char)cur);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Illegal character in signature!");
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
if (length.length() == 0 || signature.length() == 0)
|
||||
{
|
||||
throw new IOException("Broken signature!");
|
||||
}
|
||||
final int sigLength = new BigInteger(length.toString(), 36).intValue();
|
||||
if (sigLength < 0 || sigLength > 2048)
|
||||
{
|
||||
throw new IOException("Invalid signature length!");
|
||||
}
|
||||
final byte[] sigBytes = new BigInteger(signature.toString(), 36).toByteArray();
|
||||
if (sigLength < sigBytes.length)
|
||||
{
|
||||
throw new IOException("Length is less then available bytes.");
|
||||
}
|
||||
byte[] realBytes;
|
||||
if (sigLength == sigBytes.length)
|
||||
{
|
||||
realBytes = sigBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
realBytes = new byte[sigLength];
|
||||
System.arraycopy(sigBytes, 0, realBytes, sigLength - sigBytes.length, sigBytes.length);
|
||||
}
|
||||
final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(PUBLIC_KEY.toByteArray());
|
||||
final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
final PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
|
||||
final Signature rsa = Signature.getInstance("SHA256withRSA");
|
||||
rsa.initVerify(pubKey);
|
||||
final byte[] buffer = new byte[2048];
|
||||
int readLength;
|
||||
do
|
||||
{
|
||||
readLength = bis.read(buffer);
|
||||
if (readLength >= 0)
|
||||
{
|
||||
rsa.update(buffer, 0, readLength);
|
||||
}
|
||||
}
|
||||
while (readLength >= 0);
|
||||
return rsa.verify(realBytes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bis != null)
|
||||
{
|
||||
bis.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
LOGGER.log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void readVersions() throws Exception
|
||||
{
|
||||
updateConfig = new YamlConfiguration();
|
||||
updateConfig.load(file);
|
||||
versions.clear();
|
||||
for (String versionString : updateConfig.getKeys(false))
|
||||
{
|
||||
final Version version = new Version(versionString);
|
||||
final VersionInfo info = new VersionInfo(updateConfig, versionString);
|
||||
versions.put(version, info);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<Version, VersionInfo> getVersions()
|
||||
{
|
||||
return Collections.unmodifiableMap(versions.descendingMap());
|
||||
}
|
||||
}
|
@@ -0,0 +1,128 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event.Priority;
|
||||
import org.bukkit.event.Event.Type;
|
||||
import org.bukkit.event.player.PlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerListener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
|
||||
public class UpdateProcess extends PlayerListener
|
||||
{
|
||||
private transient Player currentPlayer;
|
||||
private final transient Plugin plugin;
|
||||
private final transient UpdateCheck updateCheck;
|
||||
|
||||
public UpdateProcess(final Plugin plugin, final UpdateCheck updateCheck)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.updateCheck = updateCheck;
|
||||
}
|
||||
|
||||
public void registerEvents()
|
||||
{
|
||||
final PluginManager pluginManager = plugin.getServer().getPluginManager();
|
||||
pluginManager.registerEvent(Type.PLAYER_QUIT, this, Priority.Low, plugin);
|
||||
pluginManager.registerEvent(Type.PLAYER_CHAT, this, Priority.Lowest, plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerChat(final PlayerChatEvent event)
|
||||
{
|
||||
if (event.getPlayer() == currentPlayer)
|
||||
{
|
||||
reactOnMessage(event.getMessage());
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerJoin(final PlayerJoinEvent event)
|
||||
{
|
||||
final Player player = event.getPlayer();
|
||||
if (player.hasPermission("essentials.update") && !updateCheck.isEssentialsInstalled())
|
||||
{
|
||||
player.sendMessage("Hello " + player.getDisplayName());
|
||||
player.sendMessage("Please type /essentialsupdate into the chat to start the installation of Essentials.");
|
||||
}
|
||||
if (player.hasPermission("essentials.update"))
|
||||
{
|
||||
final UpdateCheck.CheckResult result = updateCheck.getResult();
|
||||
switch (result)
|
||||
{
|
||||
case NEW_ESS:
|
||||
player.sendMessage("The new version " + updateCheck.getNewVersion().toString() + " for Essentials is available. Please type /essentialsupdate to update.");
|
||||
break;
|
||||
case NEW_BUKKIT:
|
||||
player.sendMessage("Your bukkit version is not the recommended build for Essentials, please update to version " + updateCheck.getNewBukkitVersion() + ".");
|
||||
break;
|
||||
case NEW_ESS_BUKKIT:
|
||||
player.sendMessage("There is a new version " + updateCheck.getNewVersion().toString() + " of Essentials for Bukkit " + updateCheck.getNewBukkitVersion());
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doAutomaticUpdate()
|
||||
{
|
||||
final UpdatesDownloader downloader = new UpdatesDownloader();
|
||||
final VersionInfo info = updateCheck.getNewVersionInfo();
|
||||
final List<String> changelog = info.getChangelog();
|
||||
Bukkit.getLogger().info("Essentials changelog " + updateCheck.getNewVersion().toString());
|
||||
for (String line : changelog)
|
||||
{
|
||||
Bukkit.getLogger().info(" - "+line);
|
||||
}
|
||||
downloader.start(plugin.getServer().getUpdateFolderFile(), info);
|
||||
}
|
||||
|
||||
void doManualUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void onCommand(CommandSender sender)
|
||||
{
|
||||
if (sender instanceof Player && sender.hasPermission("essentials.install"))
|
||||
{
|
||||
if (currentPlayer == null)
|
||||
{
|
||||
currentPlayer = (Player)sender;
|
||||
if (updateCheck.isEssentialsInstalled())
|
||||
{
|
||||
doManualUpdate();
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage("Thank you for choosing Essentials.");
|
||||
sender.sendMessage("The following installation wizard will guide you through the installation of Essentials.");
|
||||
sender.sendMessage("Your answers will be saved for a later update.");
|
||||
sender.sendMessage("Please answer the messages with yes or no, if not otherwise stated.");
|
||||
sender.sendMessage("Write bye/exit/quit if you want to exit the wizard at anytime.");
|
||||
|
||||
}
|
||||
}
|
||||
if (!currentPlayer.equals(sender))
|
||||
{
|
||||
sender.sendMessage("The player " + currentPlayer.getDisplayName() + " is already using the wizard.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sender.sendMessage("Please run the command as op from in game.");
|
||||
}
|
||||
}
|
||||
|
||||
private void reactOnMessage(String message)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not yet implemented");
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
public class UpdatesDownloader
|
||||
{
|
||||
|
||||
UpdatesDownloader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void start(File updateFolderFile, VersionInfo newVersion)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
173
EssentialsUpdate/src/com/earth2me/essentials/update/Version.java
Normal file
173
EssentialsUpdate/src/com/earth2me/essentials/update/Version.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class Version implements Comparable<Version>
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
STABLE, PREVIEW, DEVELOPER
|
||||
}
|
||||
|
||||
public int getMajor()
|
||||
{
|
||||
return major;
|
||||
}
|
||||
|
||||
public int getMinor()
|
||||
{
|
||||
return minor;
|
||||
}
|
||||
|
||||
public int getBuild()
|
||||
{
|
||||
return build;
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
private final transient int major;
|
||||
private final transient int minor;
|
||||
private final transient int build;
|
||||
private final transient Type type;
|
||||
|
||||
public Version(final String versionString)
|
||||
{
|
||||
final Matcher matcher = Pattern.compile("(Pre|Dev)?([0-9]+)[_\\.]([0-9]+)[_\\.]([0-9]+).*").matcher(versionString);
|
||||
if (!matcher.matches() || matcher.groupCount() < 4)
|
||||
{
|
||||
type = Type.DEVELOPER;
|
||||
major = 99;
|
||||
minor = build = 0;
|
||||
return;
|
||||
}
|
||||
if (versionString.startsWith("Pre"))
|
||||
{
|
||||
type = Type.PREVIEW;
|
||||
}
|
||||
else if (versionString.startsWith("Dev"))
|
||||
{
|
||||
type = Type.DEVELOPER;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = Type.STABLE;
|
||||
}
|
||||
major = Integer.parseInt(matcher.group(2));
|
||||
minor = Integer.parseInt(matcher.group(3));
|
||||
build = Integer.parseInt(matcher.group(4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Version other)
|
||||
{
|
||||
int ret = 0;
|
||||
if (other.getType() == Type.DEVELOPER && getType() != Type.DEVELOPER)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if (getType() == Type.DEVELOPER && other.getType() != Type.DEVELOPER)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (other.getMajor() > getMajor())
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if (getMajor() > other.getMajor())
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (other.getMinor() > getMinor())
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if (getMinor() > other.getMinor())
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (other.getBuild() > getBuild())
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if (getBuild() > other.getBuild())
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
else if (other.getType() == Type.STABLE && getType() == Type.PREVIEW)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
else if (getType() == Type.STABLE && other.getType() == Type.PREVIEW)
|
||||
{
|
||||
ret = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final Version other = (Version)obj;
|
||||
if (this.major != other.major)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.minor != other.minor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.build != other.build)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.type != other.type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 5;
|
||||
hash = 71 * hash + this.major;
|
||||
hash = 71 * hash + this.minor;
|
||||
hash = 71 * hash + this.build;
|
||||
hash = 71 * hash + (this.type != null ? this.type.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (type == Type.DEVELOPER)
|
||||
{
|
||||
builder.append("Dev");
|
||||
}
|
||||
if (type == Type.PREVIEW)
|
||||
{
|
||||
builder.append("Pre");
|
||||
}
|
||||
builder.append(major);
|
||||
builder.append('.');
|
||||
builder.append(minor);
|
||||
builder.append('.');
|
||||
builder.append(build);
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
package com.earth2me.essentials.update;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.bukkit.configuration.Configuration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class VersionInfo
|
||||
{
|
||||
private final transient List<String> changelog;
|
||||
private final transient int minBukkit;
|
||||
private final transient int maxBukkit;
|
||||
private final transient List<ModuleInfo> modules;
|
||||
|
||||
public VersionInfo(final Configuration updateConfig, final String path)
|
||||
{
|
||||
changelog = updateConfig.getList(path + ".changelog", Collections.<String>emptyList());
|
||||
minBukkit = updateConfig.getInt(path + ".min-bukkit", 0);
|
||||
maxBukkit = updateConfig.getInt(path + ".max-bukkit", 0);
|
||||
modules = new ArrayList<ModuleInfo>();
|
||||
final String modulesPath = path + ".modules";
|
||||
for (String module : updateConfig.getKeys(false))
|
||||
{
|
||||
modules.add(new ModuleInfo(updateConfig, modulesPath + module));
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getChangelog()
|
||||
{
|
||||
return Collections.unmodifiableList(changelog);
|
||||
}
|
||||
|
||||
public int getMinBukkit()
|
||||
{
|
||||
return minBukkit;
|
||||
}
|
||||
|
||||
public int getMaxBukkit()
|
||||
{
|
||||
return maxBukkit;
|
||||
}
|
||||
|
||||
public List<ModuleInfo> getModules()
|
||||
{
|
||||
return Collections.unmodifiableList(modules);
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
package com.earth2me.essentials.update.states;
|
||||
|
||||
|
||||
public class Modules
|
||||
{
|
||||
|
||||
}
|
Reference in New Issue
Block a user