<commit_before>package com.chiorichan.command.defaults;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import com.chiorichan.ChatColor;
import com.chiorichan.Loader;
import com.chiorichan.ThreadCommandReader;
import com.chiorichan.account.bases.SentientHandler;
import com.chiorichan.framework.WebUtils;
import com.chiorichan.updater.BuildArtifact;
import com.chiorichan.updater.Download;
import com.chiorichan.updater.DownloadListener;
import com.chiorichan.util.Versioning;
import com.google.common.base.Strings;

public class UpdateCommand extends ChioriCommand
{
	public UpdateCommand()
	{
		super( "update" );
		
		this.description = "Gets the version of this server including any plugins in use";
		this.usageMessage = "/update [latest]";
		this.setPermission( "chiori.command.update" );
	}
	
	@Override
	public boolean execute( SentientHandler sender, String currentAlias, String[] args )
	{
		if ( !Loader.getAutoUpdater().isEnabled() )
		{
			sender.sendMessage( ChatColor.RED + "I'm sorry but updates are disabled per configs!" );
			return true;
		}
		
		if ( Loader.getConfig().getBoolean( "auto-updater.console-only" ) && !( sender instanceof ThreadCommandReader ) )
		{
			sender.sendMessage( ChatColor.RED + "I'm sorry but updates can only be performed from the console!" );
			return true;
		}
		
		if ( !testPermission( sender ) )
			return true;
		
		if ( args.length > 0 )
		{
			if ( args[0].equalsIgnoreCase( "latest" ) )
			{
				try
				{
					if ( args.length > 1 && args[1].equalsIgnoreCase( "force" ) )
					{
						BuildArtifact latest = Loader.getAutoUpdater().getLatest();
						
						if ( latest == null )
							sender.sendMessage( ChatColor.RED + "Please review the latest version without \"force\" arg before updating." );
						else
						{
							sender.sendMessage( ChatColor.YELLOW + "Please wait as we download the latest version of Chiori Web Server..." );
							
							File currentJar = new File( URLDecoder.decode( Loader.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8" ) );
							File updatedJar = new File( "update.jar" );
							
							Download download = new Download( new URL( latest.getJar() ), updatedJar.getName(), updatedJar.getPath() );
							download.setListener( new DownloadProgressDisplay( sender ) );
							download.run();
							
							String origMD5 = new String( WebUtils.readUrl( latest.getMD5File() ) ).trim();
							
							if ( origMD5 != null && !origMD5.isEmpty() )
							{
								String descMD5 = DigestUtils.md5Hex( new FileInputStream( updatedJar.getPath() ) ).trim();
								
								if ( descMD5.equals( origMD5 ) )
									sender.sendMessage( ChatColor.AQUA + "SUCCESS: The downloaded jar and control MD5Checksum matched, '" + origMD5 + "'" );
								else
								{
									sender.sendMessage( ChatColor.RED + "ERROR: The server said the downloaded jar should have a MD5Checksum of '" + origMD5 + "' but it had the MD5Checksum '" + descMD5 + "', UPDATE ABORTED!!!" );
									FileUtils.deleteQuietly( updatedJar );
									return true;
								}
							}
							
							currentJar.delete();
							FileInputStream fis = null;
							FileOutputStream fos = null;
							try
							{
								fis = new FileInputStream( updatedJar );
								fos = new FileOutputStream( currentJar );
								IOUtils.copy( fis, fos );
							}
							catch ( IOException e )
							{
								e.printStackTrace();
							}
							finally
							{
								IOUtils.closeQuietly( fis );
								IOUtils.closeQuietly( fos );
							}
							
							updatedJar.setExecutable( true, true );
							
							String newMD5 = DigestUtils.md5Hex( new FileInputStream( currentJar.getPath() ) ).trim();
							
							if ( origMD5 != null && !origMD5.isEmpty() && newMD5.equals( origMD5 ) )
							{
								sender.sendMessage( ChatColor.AQUA + "----- Chiori Auto Updater -----" );
								sender.sendMessage( ChatColor.AQUA + "SUCCESS: The downloaded jar was successfully installed in the place of your old one." );
								sender.sendMessage( ChatColor.AQUA + "You will need to restart " + Versioning.getProduct() + " for the changes to take effect." );
								sender.sendMessage( ChatColor.AQUA + "Please type 'stop' and press enter to make this happen, otherwise you may encounter unexpected problems!" );
								sender.sendMessage( ChatColor.AQUA + "----- ------------------- -----" );
							}
							else
							{
								sender.sendMessage( ChatColor.YELLOW + "----- Chiori Auto Updater -----" );
								sender.sendMessage( ChatColor.RED + "SEVERE: There was a problem installing the downloaded jar in the place of your old one." );
								sender.sendMessage( ChatColor.RED + "Sorry about that because most likely your current jar is now currupt");
								sender.sendMessage( ChatColor.RED + "Try redownloading this version yourself from: " + latest.getJar() );
								sender.sendMessage( ChatColor.RED + "Details: " + latest.getHtmlUrl() );
								sender.sendMessage( ChatColor.YELLOW + "----- ------------------- -----" );<commit_msg>Update function now creates a backup of the currently running server.<commit_after>package com.chiorichan.command.defaults;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import com.chiorichan.ChatColor;
import com.chiorichan.Loader;
import com.chiorichan.ThreadCommandReader;
import com.chiorichan.account.bases.SentientHandler;
import com.chiorichan.framework.WebUtils;
import com.chiorichan.updater.BuildArtifact;
import com.chiorichan.updater.Download;
import com.chiorichan.updater.DownloadListener;
import com.chiorichan.util.Versioning;
import com.google.common.base.Strings;

public class UpdateCommand extends ChioriCommand
{
	public UpdateCommand()
	{
		super( "update" );
		
		this.description = "Gets the version of this server including any plugins in use";
		this.usageMessage = "/update [latest]";
		this.setPermission( "chiori.command.update" );
	}
	
	@Override
	public boolean execute( SentientHandler sender, String currentAlias, String[] args )
	{
		if ( !Loader.getAutoUpdater().isEnabled() )
		{
			sender.sendMessage( ChatColor.RED + "I'm sorry but updates are disabled per configs!" );
			return true;
		}
		
		if ( Loader.getConfig().getBoolean( "auto-updater.console-only" ) && !( sender instanceof ThreadCommandReader ) )
		{
			sender.sendMessage( ChatColor.RED + "I'm sorry but updates can only be performed from the console!" );
			return true;
		}
		
		if ( !testPermission( sender ) )
			return true;
		
		if ( args.length > 0 )
		{
			if ( args[0].equalsIgnoreCase( "latest" ) )
			{
				try
				{
					if ( args.length > 1 && args[1].equalsIgnoreCase( "force" ) )
					{
						BuildArtifact latest = Loader.getAutoUpdater().getLatest();
						
						if ( latest == null )
							sender.sendMessage( ChatColor.RED + "Please review the latest version without \"force\" arg before updating." );
						else
						{
							sender.sendMessage( ChatColor.YELLOW + "Please wait as we download the latest version of Chiori Web Server..." );
							
							File currentJar = new File( URLDecoder.decode( Loader.class.getProtectionDomain().getCodeSource().getLocation().getPath(), "UTF-8" ) );
							File updatedJar = new File( "update.jar" );
							File backupJar = new File( currentJar, ".bak" );
							
							Download download = new Download( new URL( latest.getJar() ), updatedJar.getName(), updatedJar.getPath() );
							download.setListener( new DownloadProgressDisplay( sender ) );
							download.run();
							
							String origMD5 = new String( WebUtils.readUrl( latest.getMD5File() ) ).trim();
							
							if ( origMD5 != null && !origMD5.isEmpty() )
							{
								String descMD5 = DigestUtils.md5Hex( new FileInputStream( updatedJar.getPath() ) ).trim();
								
								if ( descMD5.equals( origMD5 ) )
									sender.sendMessage( ChatColor.AQUA + "SUCCESS: The downloaded jar and control MD5Checksum matched, '" + origMD5 + "'" );
								else
								{
									sender.sendMessage( ChatColor.RED + "ERROR: The server said the downloaded jar should have a MD5Checksum of '" + origMD5 + "' but it had the MD5Checksum '" + descMD5 + "', UPDATE ABORTED!!!" );
									FileUtils.deleteQuietly( updatedJar );
									return true;
								}
							}
							
							backupJar.delete();
							FileUtils.moveFile( currentJar, backupJar );
							
							FileInputStream fis = null;
							FileOutputStream fos = null;
							try
							{
								fis = new FileInputStream( updatedJar );
								fos = new FileOutputStream( currentJar );
								IOUtils.copy( fis, fos );
							}
							catch ( IOException e )
							{
								e.printStackTrace();
							}
							finally
							{
								IOUtils.closeQuietly( fis );
								IOUtils.closeQuietly( fos );
							}
							
							updatedJar.setExecutable( true, true );
							
							String newMD5 = DigestUtils.md5Hex( new FileInputStream( currentJar.getPath() ) ).trim();
							
							if ( origMD5 != null && !origMD5.isEmpty() && newMD5.equals( origMD5 ) )
							{
								sender.sendMessage( ChatColor.AQUA + "----- Chiori Auto Updater -----" );
								sender.sendMessage( ChatColor.AQUA + "SUCCESS: The downloaded jar was successfully installed in the place of your old one." );
								sender.sendMessage( ChatColor.AQUA + "If you have a problem with the updated jar, you can find a backup jar file at: " + backupJar.getAbsolutePath() );
								sender.sendMessage( ChatColor.AQUA + "You will need to restart " + Versioning.getProduct() + " for the changes to take effect." );
								sender.sendMessage( ChatColor.AQUA + "Please type 'stop' and press enter to make this happen, otherwise you may encounter unexpected problems!" );
								sender.sendMessage( ChatColor.AQUA + "----- ------------------- -----" );
							}
							else
							{
								currentJar.delete();
								FileUtils.moveFile( backupJar, currentJar );
								
								sender.sendMessage( ChatColor.YELLOW + "----- Chiori Auto Updater -----" );
								sender.sendMessage( ChatColor.RED + "SEVERE: There was a problem installing the downloaded jar in the place of your old one." );
								sender.sendMessage( ChatColor.RED + "Don't worry we restored your original jar file.");
								sender.sendMessage( ChatColor.RED + "Try redownloading this version yourself from: " + latest.getJar() );
								sender.sendMessage( ChatColor.RED + "Details: " + latest.getHtmlUrl() );
								sender.sendMessage( ChatColor.YELLOW + "----- ------------------- -----" );
{'fraction_non_alphanumeric': 0.12446430199689978, 'fraction_numerical': 0.004559131941278381, 'mean_word_length': 2.7459016393442623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 28, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3434463', 'n_tokens_mistral': 4250, 'n_tokens_neox': 3192, 'n_words': 837}