Remove external plugin support

Jagex has requested I take steps to prevent users from making plugins
which are in violation of the game rules. This limits plugins to the core
plugins.
This commit is contained in:
Adam
2018-01-25 12:06:28 -05:00
parent f23b970212
commit f507354f84
14 changed files with 0 additions and 607 deletions

View File

@@ -42,7 +42,6 @@
<maven.javadoc.skip>true</maven.javadoc.skip>
<checkstyle.skip>true</checkstyle.skip>
<archetype.test.skip>true</archetype.test.skip>
<rs.version>161</rs.version>
</properties>
@@ -124,7 +123,6 @@
<module>runescape-client</module>
<module>runescape-client-injector</module>
<module>runescape-client-injector-plugin</module>
<module>runelite-plugin-archetype</module>
<module>http-api</module>
<module>http-service</module>
<module>protocol-api</module>

View File

@@ -55,7 +55,6 @@ public class RuneLite
{
public static final File RUNELITE_DIR = new File(System.getProperty("user.home"), ".runelite");
public static final File PROFILES_DIR = new File(RUNELITE_DIR, "profiles");
public static final File PLUGIN_DIR = new File(RUNELITE_DIR, "plugins");
public static final File SCREENSHOT_DIR = new File(RUNELITE_DIR, "screenshots");
private static Injector injector;
@@ -162,9 +161,6 @@ public class RuneLite
// Load the session, including saved configuration
sessionManager.loadSession();
// Begin watching for new plugins
pluginManager.watch();
SwingUtilities.invokeAndWait(() -> gui.showWithChrome(runeliteConfig.enableCustomChrome()));
eventBus.post(new ClientUILoaded());

View File

@@ -51,18 +51,4 @@ public interface RuneLiteConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "enablePlugins",
name = "Enable loading of external plugins",
description = "Enable loading of external plugins",
confirmationWarining = "WARNING: Using untrusted third party plugins is a SECURITY RISK\n"
+ " and can result in loss of YOUR ACCOUNT, and compromise the security\n"
+ "of your computer. Are you sure you want to do this?",
warnOnEnable = true
)
default boolean enablePlugins()
{
return false;
}
}

View File

@@ -65,9 +65,6 @@ public class PluginManager
@Inject
Scheduler scheduler;
@Inject
PluginWatcher pluginWatcher;
@Setter
boolean isOutdated;
@@ -95,11 +92,6 @@ public class PluginManager
}
}
public void watch()
{
pluginWatcher.start();
}
List<Plugin> scanAndInstantiate(ClassLoader classLoader, String packageName) throws IOException
{
boolean developerPlugins = RuneLite.getOptions().has("developer-mode");

View File

@@ -1,273 +0,0 @@
/*
* Copyright (c) 2016-2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins;
import com.google.inject.Injector;
import com.google.inject.Key;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.config.RuneLiteConfig;
@Singleton
@Slf4j
public class PluginWatcher extends Thread
{
private static final File BASE = RuneLite.PLUGIN_DIR;
private final RuneLiteConfig runeliteConfig;
private final PluginManager pluginManager;
private final WatchService watchService;
private final WatchKey watchKey;
@Inject
private ConfigManager configManager;
@Inject
public PluginWatcher(RuneLiteConfig runeliteConfig, PluginManager pluginManager) throws IOException
{
this.runeliteConfig = runeliteConfig;
this.pluginManager = pluginManager;
setName("Plugin Watcher");
setDaemon(true);
watchService = FileSystems.getDefault().newWatchService();
BASE.mkdirs();
Path dir = BASE.toPath();
watchKey = dir.register(watchService, ENTRY_MODIFY, ENTRY_DELETE);
}
public void cancel()
{
watchKey.cancel();
}
@Override
public void run()
{
if (runeliteConfig.enablePlugins())
{
scan();
}
for (;;)
{
try
{
WatchKey key = watchService.take();
Thread.sleep(50);
if (!runeliteConfig.enablePlugins())
{
key.reset();
continue;
}
for (WatchEvent<?> event : key.pollEvents())
{
Kind<?> kind = event.kind();
Path path = (Path) event.context();
File file = new File(BASE, path.toFile().getName());
log.debug("Event {} file {}", kind, file);
if (kind == ENTRY_MODIFY)
{
Plugin existing = findPluginForFile(file);
if (existing != null)
{
log.info("Reloading plugin {}", file);
unload(existing);
}
else
{
log.info("Loading plugin {}", file);
}
load(file);
}
else if (kind == ENTRY_DELETE)
{
Plugin existing = findPluginForFile(file);
if (existing != null)
{
log.info("Unloading plugin {}", file);
unload(existing);
}
}
}
key.reset();
}
catch (InterruptedException ex)
{
log.warn("error polling for plugins", ex);
}
}
}
private void scan()
{
for (File file : BASE.listFiles())
{
if (!file.getName().endsWith(".jar"))
{
continue;
}
log.info("Loading plugin from {}", file);
load(file);
}
}
private Plugin findPluginForFile(File file)
{
for (Plugin plugin : pluginManager.getPlugins())
{
if (plugin.file != null && plugin.file.equals(file))
{
return plugin;
}
}
return null;
}
private void load(File pluginFile)
{
PluginClassLoader loader;
try
{
loader = new PluginClassLoader(pluginFile, getClass().getClassLoader());
}
catch (MalformedURLException ex)
{
log.warn("Error loading plugin", ex);
return;
}
List<Plugin> loadedPlugins;
try
{
loadedPlugins = pluginManager.scanAndInstantiate(loader, null);
}
catch (IOException ex)
{
close(loader);
log.warn("Error loading plugin", ex);
return;
}
if (loadedPlugins.isEmpty())
{
close(loader);
log.warn("No plugin found in plugin {}", pluginFile);
return;
}
if (loadedPlugins.size() != 1)
{
close(loader);
log.warn("You can not have more than one plugin per jar");
return;
}
Plugin plugin = loadedPlugins.get(0);
plugin.file = pluginFile;
plugin.loader = loader;
// Initialize default configuration
Injector injector = plugin.getInjector();
for (Key<?> key : injector.getAllBindings().keySet())
{
Class<?> type = key.getTypeLiteral().getRawType();
if (Config.class.isAssignableFrom(type))
{
Config config = (Config) injector.getInstance(key);
configManager.setDefaultConfiguration(config);
}
}
try
{
pluginManager.startPlugin(plugin);
}
catch (PluginInstantiationException ex)
{
close(loader);
log.warn("unable to start plugin", ex);
return;
}
// Plugin is now running
pluginManager.add(plugin);
}
private void unload(Plugin plugin)
{
try
{
pluginManager.stopPlugin(plugin);
}
catch (PluginInstantiationException ex)
{
log.warn("unable to stop plugin", ex);
}
pluginManager.remove(plugin); // remove it regardless
close(plugin.loader);
}
private void close(URLClassLoader classLoader)
{
try
{
classLoader.close();
}
catch (IOException ex1)
{
log.warn(null, ex1);
}
}
}

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2017, Adam <Adam@sigterm.info>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.runelite</groupId>
<artifactId>runelite-parent</artifactId>
<version>1.2.13-SNAPSHOT</version>
</parent>
<artifactId>runelite-plugin-archetype</artifactId>
<packaging>maven-archetype</packaging>
<name>RuneLite Plugin Archetype</name>
<build>
<!-- filter archetype resource's pom to put project version in it -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>archetype-resources/pom.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>archetype-resources/pom.xml</exclude>
</excludes>
</resource>
</resources>
<extensions>
<extension>
<groupId>org.apache.maven.archetype</groupId>
<artifactId>archetype-packaging</artifactId>
<version>3.0.1</version>
</extension>
</extensions>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-archetype-plugin</artifactId>
<version>3.0.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<!-- allow escaping variables in filtered
resources - https://stackoverflow.com/a/7223084
-->
<configuration>
<escapeString>\</escapeString>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archetype-descriptor xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd" name="example-plugin"
xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<fileSets>
<fileSet filtered="true" packaged="true" encoding="UTF-8">
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</fileSet>
</fileSets>
</archetype-descriptor>

View File

@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>\${groupId}</groupId>
<artifactId>\${artifactId}</artifactId>
<version>\${version}</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>runelite</id>
<name>RuneLite</name>
<url>http://repo.runelite.net</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.runelite</groupId>
<artifactId>client</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>install</phase>
<configuration>
<target>
<copy file="\${project.build.directory}/\${project.build.finalName}.jar" tofile="\${user.home}/.runelite/plugins/\${project.build.finalName}.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,47 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package};
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.annotation.Nullable;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
public class ExampleOverlay extends Overlay
{
private final Client client;
private final ExamplePluginConfiguration config;
@Inject
public ExampleOverlay(@Nullable Client client, ExamplePluginConfiguration config)
{
setPosition(OverlayPosition.DYNAMIC);
this.client = client;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics, java.awt.Point parent)
{
if (client.getGameState() != GameState.LOGGED_IN || !config.enabled())
{
return null;
}
Player player = client.getLocalPlayer();
String text = player.getName() + " (Level: " + player.getCombatLevel() + ")";
Point textLocation = player.getCanvasTextLocation(graphics, text, player.getModelHeight());
graphics.drawString(text, textLocation.getX(), textLocation.getY());
return null;
}
}

View File

@@ -1,73 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package};
import com.google.common.eventbus.Subscribe;
import com.google.inject.Binder;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.ChatMessageType;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.Overlay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@PluginDescriptor(
name = "Example plugin"
)
public class ExamplePlugin extends Plugin
{
private static final Logger logger = LoggerFactory.getLogger(ExamplePlugin.class);
@Inject
Client client;
@Inject
ExampleOverlay overlay;
@Override
protected void startUp() throws Exception
{
logger.info("Example plugin started!");
}
@Override
protected void shutDown() throws Exception
{
logger.info("Example plugin stopped!");
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged)
{
if (gameStateChanged.getGameState() == GameState.LOGGED_IN)
{
client.sendGameMessage(ChatMessageType.GAME, "Example plugin is running!");
}
}
@Override
public void configure(Binder binder)
{
binder.bind(ExampleOverlay.class);
}
@Override
public Overlay getOverlay()
{
return overlay;
}
@Provides
ExamplePluginConfiguration provideConfig(ConfigManager configManager)
{
return configManager.getConfig(ExamplePluginConfiguration.class);
}
}

View File

@@ -1,26 +0,0 @@
#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package};
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "exampleplugin",
name = "Example plugin",
description = "Configuration for example plugin"
)
public interface ExamplePluginConfiguration extends Config
{
@ConfigItem(
keyName = "enabled",
name = "Enable overlay",
description = "Configures whether the overlay is enabled"
)
default boolean enabled()
{
return true;
}
}

View File

@@ -1,5 +0,0 @@
sourceEncoding=UTF-8
groupId=org.example.runelite
artifactId=exampleplugin
version=1.0.0-SNAPSHOT
package=org.example.runelite.exampleplugin

View File

@@ -265,7 +265,6 @@ under the License.
<runelite.tomcat.url>http://api.runelite.net/manager/text</runelite.tomcat.url>
<maven.javadoc.skip>false</maven.javadoc.skip>
<checkstyle.skip>false</checkstyle.skip>
<archetype.test.skip>false</archetype.test.skip>
</properties>
</profile>
</profiles>