mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-07-14 07:52:59 +00:00

The HTTP filtering system becomes even more complex! Though in this case, it's pretty minimal, and definitely worth doing. For instance, the following rule will allow connecting to localhost on port :8080. [[http.rules]] host = "127.0.0.1" port = 8080 action = "allow" # Other rules as before. Closes #540
136 lines
5.5 KiB
Java
136 lines
5.5 KiB
Java
/*
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
|
|
package dan200.computercraft.core.apis.http.options;
|
|
|
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
|
import com.electronwill.nightconfig.core.Config;
|
|
import com.electronwill.nightconfig.core.InMemoryCommentedFormat;
|
|
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
|
import dan200.computercraft.ComputerCraft;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.Locale;
|
|
import java.util.Optional;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
/**
|
|
* Parses, checks and generates {@link Config}s for {@link AddressRule}.
|
|
*/
|
|
public class AddressRuleConfig
|
|
{
|
|
public static UnmodifiableConfig makeRule( String host, Action action )
|
|
{
|
|
CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new );
|
|
config.add( "host", host );
|
|
config.add( "action", action.name().toLowerCase( Locale.ROOT ) );
|
|
|
|
if( host.equals( "*" ) && action == Action.ALLOW )
|
|
{
|
|
config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." );
|
|
config.add( "timeout", AddressRule.TIMEOUT );
|
|
|
|
config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." );
|
|
config.set( "max_download", AddressRule.MAX_DOWNLOAD );
|
|
|
|
config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." );
|
|
config.set( "max_upload", AddressRule.MAX_UPLOAD );
|
|
|
|
config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." );
|
|
config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE );
|
|
}
|
|
|
|
return config;
|
|
}
|
|
|
|
public static boolean checkRule( UnmodifiableConfig builder )
|
|
{
|
|
String hostObj = get( builder, "host", String.class ).orElse( null );
|
|
Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
|
|
return hostObj != null && checkEnum( builder, "action", Action.class )
|
|
&& check( builder, "port", Number.class )
|
|
&& check( builder, "timeout", Number.class )
|
|
&& check( builder, "max_upload", Number.class )
|
|
&& check( builder, "max_download", Number.class )
|
|
&& check( builder, "websocket_message", Number.class )
|
|
&& AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null;
|
|
}
|
|
|
|
@Nullable
|
|
public static AddressRule parseRule( UnmodifiableConfig builder )
|
|
{
|
|
String hostObj = get( builder, "host", String.class ).orElse( null );
|
|
if( hostObj == null ) return null;
|
|
|
|
Action action = getEnum( builder, "action", Action.class ).orElse( null );
|
|
Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null );
|
|
Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null );
|
|
Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null );
|
|
Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null );
|
|
Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null );
|
|
|
|
PartialOptions options = new PartialOptions(
|
|
action,
|
|
maxUpload,
|
|
maxDownload,
|
|
timeout,
|
|
websocketMessage
|
|
);
|
|
|
|
return AddressRule.parse( hostObj, port, options );
|
|
}
|
|
|
|
private static <T> boolean check( UnmodifiableConfig config, String field, Class<T> klass )
|
|
{
|
|
Object value = config.get( field );
|
|
if( value == null || klass.isInstance( value ) ) return true;
|
|
|
|
ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() );
|
|
return false;
|
|
}
|
|
|
|
private static <T extends Enum<T>> boolean checkEnum( UnmodifiableConfig config, String field, Class<T> klass )
|
|
{
|
|
Object value = config.get( field );
|
|
if( value == null ) return true;
|
|
|
|
if( !(value instanceof String) )
|
|
{
|
|
ComputerCraft.log.warn( "HTTP rule's {} is not a string", field );
|
|
return false;
|
|
}
|
|
|
|
if( parseEnum( klass, (String) value ) == null )
|
|
{
|
|
ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field );
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static <T> Optional<T> get( UnmodifiableConfig config, String field, Class<T> klass )
|
|
{
|
|
Object value = config.get( field );
|
|
return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty();
|
|
}
|
|
|
|
private static <T extends Enum<T>> Optional<T> getEnum( UnmodifiableConfig config, String field, Class<T> klass )
|
|
{
|
|
return get( config, field, String.class ).map( x -> parseEnum( klass, x ) );
|
|
}
|
|
|
|
@Nullable
|
|
private static <T extends Enum<T>> T parseEnum( Class<T> klass, String x )
|
|
{
|
|
for( T value : klass.getEnumConstants() )
|
|
{
|
|
if( value.name().equalsIgnoreCase( x ) ) return value;
|
|
}
|
|
return null;
|
|
}
|
|
}
|