package com.laytonsmith.core.functions;
import com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery;
import com.laytonsmith.PureUtilities.Common.StreamUtils;
import com.laytonsmith.PureUtilities.Version;
import com.laytonsmith.abstraction.Implementation;
import com.laytonsmith.abstraction.MCBlockCommandSender;
import com.laytonsmith.abstraction.MCCommandSender;
import com.laytonsmith.abstraction.MCLocation;
import com.laytonsmith.abstraction.MCPlayer;
import com.laytonsmith.annotations.api;
import com.laytonsmith.annotations.noboilerplate;
import com.laytonsmith.core.AliasCore;
import com.laytonsmith.core.CHLog;
import com.laytonsmith.core.CHVersion;
import com.laytonsmith.core.LogLevel;
import com.laytonsmith.core.ObjectGenerator;
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.Prefs;
import com.laytonsmith.core.Script;
import com.laytonsmith.core.Static;
import com.laytonsmith.core.constructs.CArray;
import com.laytonsmith.core.constructs.CBoolean;
import com.laytonsmith.core.constructs.CInt;
import com.laytonsmith.core.constructs.CNull;
import com.laytonsmith.core.constructs.CResource;
import com.laytonsmith.core.constructs.CString;
import com.laytonsmith.core.constructs.CVoid;
import com.laytonsmith.core.constructs.Construct;
import com.laytonsmith.core.constructs.Target;
import com.laytonsmith.core.environments.CommandHelperEnvironment;
import com.laytonsmith.core.environments.Environment;
import com.laytonsmith.core.environments.GlobalEnv;
import com.laytonsmith.core.exceptions.CRE.CREFormatException;
import com.laytonsmith.core.exceptions.CRE.CREIOException;
import com.laytonsmith.core.exceptions.CRE.CREPlayerOfflineException;
import com.laytonsmith.core.exceptions.CRE.CREPluginInternalException;
import com.laytonsmith.core.exceptions.CRE.CREThrowable;
import com.laytonsmith.core.exceptions.CancelCommandException;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.jar.JarFile;
import java.util.Locale;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
/**
*
*/
public class Meta {
public static String docs() {
return "These functions provide a way to run other commands";
}
/*
@api
public static class first_load extends AbstractFunction {
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{};
}
public boolean isRestricted() {
return false;
}
public Boolean runAsync() {
return false;
}
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
return CBoolean.get(CommandHelperPlugin.isFirstLoad());
}
public String getName() {
return "first_load";
}
public Integer[] numArgs() {
return new Integer[]{0};
}
public String docs() {
return "boolean {} Returns true if the scripts have not been reloaded since the plugin was enabled."
+ " In otherwords, using this in main.ms will return false when you do /reloadaliases.";
}
public Version since() {
return CHVersion.V3_3_1;
}
}
*/
@api(environments = {CommandHelperEnvironment.class})
public static class runas extends AbstractFunction {
@Override
public String getName() {
return "runas";
}
@Override
public Integer[] numArgs() {
return new Integer[]{2};
}
@Override
public Construct exec(Target t, final Environment env, Construct... args) throws CancelCommandException, ConfigRuntimeException {
if (args[1].nval() == null || args[1].val().length() <= 0 || args[1].val().charAt(0) != '/') {
throw new CREFormatException("The first character of the command must be a forward slash (i.e. '/give')", t);
}
String cmd = args[1].val().substring(1);
if (args[0] instanceof CArray) {
CArray u = (CArray) args[0];
for (int i = 0; i < u.size(); i++) {
exec(t, env, new Construct[]{new CString(u.get(i, t).val(), t), args[1]});
}
return CVoid.VOID;
}
if (args[0].val().equals("~op")) {
//TODO: Remove this after next release (3.3.1)
CHLog.GetLogger().Log(CHLog.Tags.DEPRECATION, LogLevel.WARNING, "Using runas(~op, " + args[1].asString().getQuote()
+ ") is deprecated. Use sudo(" + args[1].asString().getQuote() + ") instead.", t);
new sudo().exec(t, env, args[1]);
} else if (args[0].val().equals(Static.getConsoleName())) {
CHLog.GetLogger().Log(CHLog.Tags.META, LogLevel.INFO, "Executing command on " + (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null ? env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName() : "console") + " (as console): " + args[1].val().trim(), t);
if (Prefs.DebugMode()) {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null ? env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName() : "console") + " (as : " + args[1].val().trim());
}
if(cmd.equalsIgnoreCase("interpreter-on")){
//This isn't allowed for security reasons.
throw new CREFormatException("/interpreter-on cannot be run from runas for security reasons.", t);
}
Static.getServer().runasConsole(cmd);
} else {
MCPlayer m = Static.GetPlayer(args[0], t);
if (m != null && m.isOnline()) {
MCPlayer p = env.getEnv(CommandHelperEnvironment.class).GetPlayer();
String name;
if (p != null) {
name = p.getName();
} else {
name = "Unknown player";
}
CHLog.GetLogger().Log(CHLog.Tags.META, LogLevel.INFO, "Executing command on " + name + " (running as " + args[0].val() + "): " + args[1].val().trim(), t);
if (Prefs.DebugMode()) {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + name + " (running as " + args[0].val() + "): " + args[1].val().trim());
}
//m.chat(cmd);
Static.getServer().dispatchCommand(m, cmd);
} else {
throw new CREPlayerOfflineException("The player " + args[0].val() + " is not online", t);
}
}
return CVoid.VOID;
}
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREFormatException.class, CREPlayerOfflineException.class};
}
@Override
public String docs() {
return "void {player, command} Runs a command as a particular user. The special user '" + Static.getConsoleName() + "' can be used to run it as a console"
+ " user. Using '~op' is deprecated, and will be removed after the next release, use sudo() instead."
+ " Commands cannot be run as an offline player. If the first argument is an array of usernames, the command"
+ " will be run in the context of each user in the array.";
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public CHVersion since() {
return CHVersion.V3_0_1;
}
@Override
public Boolean runAsync() {
return false;
}
}
@api(environments = {CommandHelperEnvironment.class})
public static class sudo extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREFormatException.class};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return false;
}
@Override
public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException {
if (args[0].nval() == null || args[0].val().length() <= 0 || args[0].val().charAt(0) != '/') {
throw new CREFormatException("The first character of the command must be a forward slash (i.e. '/give')", t);
}
String cmd = args[0].val().substring(1);
//If the command sender is null, then just try to run() this. It's unclear to me what
//would cause this for sure, but just in case. Regardless, this allows us to consolidate the error checking
//into the run function
if(env.getEnv(CommandHelperEnvironment.class).GetCommandSender() == null){
return new run().exec(t, env, args);
}
//Store their current op status
Boolean isOp = env.getEnv(CommandHelperEnvironment.class).GetCommandSender().isOp();
CHLog.GetLogger().Log(CHLog.Tags.META, LogLevel.INFO, "Executing command on " + (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null ? env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName() : "console") + " (as op): " + args[0].val().trim(), t);
if (Prefs.DebugMode()) {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null ? env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName() : "console") + " (as op): " + args[0].val().trim());
}
//If they aren't op, op them now
if (!isOp) {
this.setOp(env.getEnv(CommandHelperEnvironment.class).GetCommandSender(), true);
}
try {
Static.getServer().dispatchCommand(this.getOPCommandSender(env.getEnv(CommandHelperEnvironment.class).GetCommandSender()), cmd);
} finally {
//If they just opped themselves, or deopped themselves in the command
//don't undo what they just did. Otherwise, set their op status back
//to their original status
if (env.getEnv(CommandHelperEnvironment.class).GetPlayer() != null
&& !cmd.equalsIgnoreCase("op " + env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName())
&& !cmd.equalsIgnoreCase("deop " + env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName())) {
this.setOp(env.getEnv(CommandHelperEnvironment.class).GetCommandSender(), isOp);
}
}
return CVoid.VOID;
}
@Override
public String getName() {
return "sudo";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "void {command} Runs a single command for this user, as op. Works like runas(~op, '/command') used to work,"
+ " before it was deprecated. ---- This is guaranteed to not allow the player to stay op, even if a fatal"
+ " error occurs during the command. If this guarantee cannot be met, the function will simply fail. This"
+ " guarantee only exists in CraftBukkit. Other server types may find that this function does not work at"
+ " all, if that's the case, and you are ok with losing the deop guarantee, you can set use-sudo-fallback"
+ " to true in your preferences. If the normal sudo functionality fails on your server then, it will"
+ " actually fully op the player, run the command, then deop the player, however, this is less reliable than"
+ " the normal sudo mechanism, and could potentially fail, leaving the player as op, so is not recommended."
+ " Enable that setting at your own risk.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
/**
* Set OP status for player without saving to ops.txt
*
* @param player
* @param value
*/
protected void setOp(MCCommandSender player, Boolean value) {
if (!(player instanceof MCPlayer) || player.isOp() == value) {
return;
}
MCPlayer p = (MCPlayer) player;
try {
p.setTempOp(value);
} catch (Exception e) {
if(Prefs.UseSudoFallback()){
p.setOp(value);
} else {
Static.getLogger().log(Level.WARNING, "[CommandHelper]: Failed to OP player " + player.getName());
StreamUtils.GetSystemErr().println("Extra information about the error: ");
e.printStackTrace();
}
}
}
protected MCCommandSender getOPCommandSender(final MCCommandSender sender) {
if (sender.isOp()) {
return sender;
}
return (MCCommandSender) Proxy.newProxyInstance(sender.getClass().getClassLoader(),
new Class[]{(sender instanceof MCPlayer) ? MCPlayer.class : MCCommandSender.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
if ("isOp".equals(methodName) || "hasPermission".equals(methodName) || "isPermissionSet".equals(methodName)) {
return true;
} else {
return method.invoke(sender, args);
}
}
});
}
}
@api(environments = {CommandHelperEnvironment.class})
public static class run extends AbstractFunction {
@Override
public String getName() {
return "run";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public Construct exec(Target t, Environment env, Construct... args) throws CancelCommandException, ConfigRuntimeException {
if (args[0].nval() == null || args[0].val().length() <= 0 || args[0].val().charAt(0) != '/') {
throw new CREFormatException("The first character of the command must be a forward slash (i.e. '/give')", t);
}
String cmd = args[0].val().substring(1);
if (Prefs.DebugMode()) {
if (env.getEnv(CommandHelperEnvironment.class).GetCommandSender() instanceof MCPlayer) {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command on " + env.getEnv(CommandHelperEnvironment.class).GetPlayer().getName() + ": " + args[0].val().trim());
} else {
Static.getLogger().log(Level.INFO, "[CommandHelper]: Executing command from console equivalent: " + args[0].val().trim());
}
}
if(cmd.equalsIgnoreCase("interpreter-on")){
throw new CREFormatException("/interpreter-on cannot be run as apart of an alias for security reasons.", t);
}
try{
Static.getServer().dispatchCommand(env.getEnv(CommandHelperEnvironment.class).GetCommandSender(), cmd);
} catch(Exception ex){
throw new CREPluginInternalException("While running the command: \"" + cmd + "\""
+ " the plugin threw an unexpected exception (turn on debug mode to see the full"
+ " stacktrace): " + ex.getMessage() + "\n\nThis is not a bug in " + Implementation.GetServerType().getBranding()
+ " but in the plugin that provides the command.", t, ex);
}
return CVoid.VOID;
}
@Override
public String docs() {
return "void {var1} Runs a command as the current player. Useful for running commands in a loop. Note that this accepts commands like from the "
+ "chat; with a forward slash in front.";
}
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREFormatException.class, CREPluginInternalException.class};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public CHVersion since() {
return CHVersion.V3_0_1;
}
@Override
public Boolean runAsync() {
return false;
}
}
@api(environments = {CommandHelperEnvironment.class, GlobalEnv.class})
public static class is_alias extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREIOException.class};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public CBoolean exec(Target t, Environment environment, Construct... args)
throws ConfigRuntimeException {
AliasCore ac = Static.getAliasCore();
for (Script s : ac.getScripts()) {
if (s.match(args[0].val())) {
return CBoolean.TRUE;
}
}
return CBoolean.FALSE;
}
@Override
public String getName() {
return "is_alias";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "boolean {cmd} Returns true if using call_alias with this cmd would trigger an alias.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
}
@api(environments = {CommandHelperEnvironment.class})
public static class call_alias extends AbstractFunction {
@Override
public String getName() {
return "call_alias";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "boolean {cmd} Allows a CommandHelper alias to be called from within another alias. Typically this is not possible, as"
+ " a script that runs \"/jail = /jail\" for instance, would simply be calling whatever plugin that actually"
+ " provides the jail functionality's /jail command. However, using this function makes the command loop back"
+ " to CommandHelper only. ---- Returns true if the command was run, or false otherwise. Note however that if an alias"
+ " ends up throwing an exception to the top level, it will not bubble up to this script, it will be caught and dealt"
+ " with already; if this happens, this function will still return true, because essentially the return value"
+ " simply indicates if the command matches an alias. Also, it is worth noting that this will trigger a player's"
+ " personal alias possibly.";
}
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public CHVersion since() {
return CHVersion.V3_2_0;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException {
boolean doRemoval = true;
if (!Static.getAliasCore().hasPlayerReference(env.getEnv(CommandHelperEnvironment.class).GetCommandSender())) {
doRemoval = false;
}
if (doRemoval) {
Static.getAliasCore().removePlayerReference(env.getEnv(CommandHelperEnvironment.class).GetCommandSender());
}
boolean ret = Static.getAliasCore().alias(args[0].val(), env.getEnv(CommandHelperEnvironment.class).GetCommandSender());
if (doRemoval) {
Static.getAliasCore().addPlayerReference(env.getEnv(CommandHelperEnvironment.class).GetCommandSender());
}
return CBoolean.get(ret);
}
}
@api(environments = {CommandHelperEnvironment.class, GlobalEnv.class})
public static class scriptas extends AbstractFunction {
@Override
public String getName() {
return "scriptas";
}
@Override
public Integer[] numArgs() {
return new Integer[]{2, 3};
}
@Override
public String docs() {
return "void {player, [label], script} Runs the specified script in the context of a given player."
+ " A script that runs player() for instance, would return the specified player's name,"
+ " not the player running the command. Setting the label allows you to dynamically set the label"
+ " this script is run under as well (in regards to permission checking)";
}
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREPlayerOfflineException.class};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public boolean preResolveVariables() {
return false;
}
@Override
public CHVersion since() {
return CHVersion.V3_3_0;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) {
return null;
}
@Override
public Construct execs(Target t, Environment environment, Script parent, ParseTree... nodes) throws ConfigRuntimeException {
MCPlayer p = Static.GetPlayer(parent.seval(nodes[0], environment).val(), t);
MCCommandSender originalPlayer = environment.getEnv(CommandHelperEnvironment.class).GetCommandSender();
int offset = 0;
String originalLabel = environment.getEnv(GlobalEnv.class).GetLabel();
if (nodes.length == 3) {
offset++;
String label = environment.getEnv(GlobalEnv.class).GetScript().seval(nodes[1], environment).val();
environment.getEnv(GlobalEnv.class).SetLabel(label);
environment.getEnv(GlobalEnv.class).GetScript().setLabel(label);
}
environment.getEnv(CommandHelperEnvironment.class).SetPlayer(p);
ParseTree tree = nodes[1 + offset];
environment.getEnv(GlobalEnv.class).GetScript().eval(tree, environment);
environment.getEnv(CommandHelperEnvironment.class).SetCommandSender(originalPlayer);
environment.getEnv(GlobalEnv.class).SetLabel(originalLabel);
environment.getEnv(GlobalEnv.class).GetScript().setLabel(originalLabel);
return CVoid.VOID;
}
@Override
public boolean useSpecialExec() {
return true;
}
}
@api(environments = {CommandHelperEnvironment.class})
public static class get_cmd extends AbstractFunction {
@Override
public String getName() {
return "get_cmd";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "mixed {} Gets the command (as a string) that ended up triggering this script, exactly"
+ " how it was entered by the player. This could be null, if for instance"
+ " it is called from within an event.";
}
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
if (environment.getEnv(CommandHelperEnvironment.class).GetCommand() == null) {
return CNull.NULL;
} else {
return new CString(environment.getEnv(CommandHelperEnvironment.class).GetCommand(), t);
}
}
@Override
public CHVersion since() {
return CHVersion.V3_3_0;
}
}
@api(environments = {CommandHelperEnvironment.class, GlobalEnv.class})
public static class capture_runas extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREPlayerOfflineException.class, CREFormatException.class,
CREPluginInternalException.class};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return false;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
String player = args[0].val();
String cmd = args[1].val();
if(!cmd.startsWith("/")){
throw new CREFormatException("Command must begin with a /", t);
}
cmd = cmd.substring(1);
MCCommandSender operator = Static.GetCommandSender(player, t);
String ret;
try {
ret = Static.getServer().dispatchAndCaptureCommand(operator, cmd);
} catch(Exception ex){
throw new CREPluginInternalException(ex.getMessage(), t, ex);
}
return new CString(ret, t);
}
@Override
public String getName() {
return "capture_runas";
}
@Override
public Integer[] numArgs() {
return new Integer[]{2};
}
@Override
public String docs() {
return "string {player, command} Works like runas, except any messages sent to the command sender during command execution are attempted to be"
+ " intercepted, and are then returned as a string, instead of being sent to the command sender. Note that this is VERY easy"
+ " for plugins to get around in such a way that this function will not work, this is NOT a bug in CommandHelper, nor is it necessarily"
+ " a problem in the other plugin either, but the other plugin will have to make changes for it to work properly."
+ " A PluginInternalException is thrown if something goes wrong. Any number of things may go wrong that aren't necessarily"
+ " this function's fault, and in those cases, this exception is thrown.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
}
@api(environments={CommandHelperEnvironment.class})
public static class get_command_block extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return null;
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return false;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
MCBlockCommandSender cs = environment.getEnv(CommandHelperEnvironment.class).GetBlockCommandSender();
if(cs != null){
MCLocation l = (cs.getBlock().getLocation());
return ObjectGenerator.GetGenerator().location(l);
}
return CNull.NULL;
}
@Override
public String getName() {
return "get_command_block";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "locationArray {} If this command was being run from a command block, this will return the location of"
+ " the block. If a player or console ran this command, (or any other command sender) this will return null.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
}
@api(environments = {CommandHelperEnvironment.class})
public static class psetop extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREPlayerOfflineException.class};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return false;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
MCPlayer player;
boolean state;
if (args.length == 1) {
player = environment.getEnv(CommandHelperEnvironment.class).GetPlayer();
Static.AssertPlayerNonNull(player, t);
state = Static.getBoolean(args[0]);
} else {
player = Static.GetPlayer(args[0].val(), t);
state = Static.getBoolean(args[1]);
}
player.setOp(state);
return CVoid.VOID;
}
@Override
public String getName() {
return "psetop";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1, 2};
}
@Override
public String docs() {
return "string {[player], status} Sets whether or not a player has operator status. If no player is specified the player running the script is given.";
}
@Override
public CHVersion since() {
return CHVersion.V3_3_1;
}
}
@api(environments = CommandHelperEnvironment.class)
public static class run_cmd extends AbstractFunction {
private final static run run = new run();
private final static call_alias call_alias = new call_alias();
private final static is_alias is_alias = new is_alias();
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{CREFormatException.class};
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return false;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CString s;
if(args[0] instanceof CString){
s = (CString)args[0];
} else {
s = new CString(args[0].val(), t);
}
if(is_alias.exec(t, environment, s).getBoolean()){
call_alias.exec(t, environment, s);
} else {
run.exec(t, environment, s);
}
return CVoid.VOID;
}
@Override
public String getName() {
return "run_cmd";
}
@Override
public Integer[] numArgs() {
return new Integer[]{1};
}
@Override
public String docs() {
return "void {cmd} Runs a command regardless of whether or not it is an alias or a builtin command. Essentially,"
+ " this works like checking if(is_alias(@cmd)){ call_alias(@cmd) } else { run(@cmd) }. Be careful with"
+ " this command, as like call_alias(), you could accidentally create infinite loops. The command must"
+ " start with a / or this will throw a FormatException.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
@api
public static class noop extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return null;
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
return CVoid.VOID;
}
@Override
public String getName() {
return "noop";
}
@Override
public Integer[] numArgs() {
return new Integer[]{Integer.MAX_VALUE};
}
@Override
public String docs() {
return "void {[...]} An operation that does nothing. Any arguments passed in are ignored entirely.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
@api
public static class get_locales extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return null;
}
@Override
public boolean isRestricted() {
return false;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public CArray exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
CArray c = new CArray(t);
for(Locale l : Locale.getAvailableLocales()){
if(!l.getCountry().equals("")){
c.push(new CString(l.toString(), t), t);
}
}
new ArrayHandling.array_sort().exec(t, environment, c);
c = new ArrayHandling.array_unique().exec(t, environment, c);
return c;
}
@Override
public String getName() {
return "get_locales";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "array {} Returns a list of locales on this system.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
@Override
public ExampleScript[] examples() throws ConfigCompileException {
return new ExampleScript[]{
new ExampleScript("Basic usage", "get_locales()")
};
}
}
@api
public static class engine_build_date extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return null;
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
JarFile jf;
try {
String jar = ClassDiscovery.GetClassContainer(Meta.class).toString();
jar = jar.replaceFirst("file:[\\|/]", "");
jf = new JarFile(jar);
} catch (IOException ex) {
return CNull.NULL;
}
ZipEntry manifest = jf.getEntry("META-INF/MANIFEST.MF");
long manifestTime = manifest.getTime();
return new CInt(manifestTime, t);
}
@Override
public String getName() {
return "engine_build_date";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "int {} Returns the compile date, in a millisecond unit time stamp, of when " + Implementation.GetServerType().getBranding() + " was compiled,"
+ " or null, if that can't be computed for various reasons.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
@api
@noboilerplate
public static class build_date extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return null;
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
return new CInt(environment.getEnv(GlobalEnv.class).GetScript().getCompileTime(), t);
}
@Override
public String getName() {
return "build_date";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "int {} Returns the compile date of the current script, as a unix time stamp in milliseconds.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
@api
public static class get_script_environment extends AbstractFunction {
@Override
public Class<? extends CREThrowable>[] thrown() {
return new Class[]{};
}
@Override
public boolean isRestricted() {
return true;
}
@Override
public Boolean runAsync() {
return null;
}
@Override
public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException {
return new CResource<>(environment, t);
}
@Override
public String getName() {
return "get_script_environment";
}
@Override
public Integer[] numArgs() {
return new Integer[]{0};
}
@Override
public String docs() {
return "resource {} Returns a copy of the underlying engine's environment object. This is only useful to embedded scripting"
+ " engines that are attempting to call back into " + Implementation.GetServerType().getBranding() + ". The object returned"
+ " is a CResource.";
}
@Override
public Version since() {
return CHVersion.V3_3_1;
}
}
}