2019-01-01 01:10:18 +00:00
|
|
|
/*
|
|
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
|
|
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
|
|
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
|
|
*/
|
|
|
|
|
2017-06-11 20:40:08 +00:00
|
|
|
package dan200.computercraft.core.apis;
|
|
|
|
|
|
|
|
import com.google.common.net.InetAddresses;
|
|
|
|
import dan200.computercraft.ComputerCraft;
|
|
|
|
|
|
|
|
import java.net.Inet6Address;
|
|
|
|
import java.net.InetAddress;
|
|
|
|
import java.util.ArrayList;
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
import java.util.Arrays;
|
2017-06-11 20:40:08 +00:00
|
|
|
import java.util.List;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Used to determine whether a domain or IP address matches a series of patterns.
|
|
|
|
*/
|
|
|
|
public class AddressPredicate
|
|
|
|
{
|
2019-03-29 21:21:39 +00:00
|
|
|
private static final class HostRange
|
2017-06-11 20:40:08 +00:00
|
|
|
{
|
|
|
|
private final byte[] min;
|
|
|
|
private final byte[] max;
|
|
|
|
|
|
|
|
private HostRange( byte[] min, byte[] max )
|
|
|
|
{
|
|
|
|
this.min = min;
|
|
|
|
this.max = max;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean contains( InetAddress address )
|
|
|
|
{
|
|
|
|
byte[] entry = address.getAddress();
|
|
|
|
if( entry.length != min.length ) return false;
|
|
|
|
|
|
|
|
for( int i = 0; i < entry.length; i++ )
|
|
|
|
{
|
2018-12-23 17:46:58 +00:00
|
|
|
int value = 0xFF & entry[i];
|
|
|
|
if( value < (0xFF & min[i]) || value > (0xFF & max[i]) ) return false;
|
2017-06-11 20:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private final List<Pattern> wildcards;
|
|
|
|
private final List<HostRange> ranges;
|
|
|
|
|
|
|
|
public AddressPredicate( String... filters )
|
Update CC: Tweaked to 1.13
Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.
Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:
- Flatten everything. For instance, there are now three instances of
BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
more BlockPeripheral (thank heavens) - there's separate block classes
for each peripheral type.
- Remove pretty much all legacy code. As we're breaking world
compatibility anyway, we can remove all the code to load worlds from
1.4 days.
- The command system is largely rewriten to take advantage of 1.13's
new system. It's very fancy!
- WidgetTerminal now uses Minecraft's "GUI listener" system.
- BREAKING CHANGE: All the codes in keys.lua are different, due to the
move to LWJGL 3. Hopefully this won't have too much of an impact.
I don't want to map to the old key codes on the Java side, as there
always ends up being small but slight inconsistencies. IMO it's
better to make a clean break - people should be using keys rather
than hard coding the constants anyway.
- commands.list now allows fetching sub-commands. The ROM has already
been updated to allow fancy usage such as commands.time.set("noon").
- Turtles, modems and cables can be waterlogged.
2019-04-02 12:27:27 +00:00
|
|
|
{
|
|
|
|
this( Arrays.asList( filters ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
public AddressPredicate( Iterable<? extends String> filters )
|
2017-06-11 20:40:08 +00:00
|
|
|
{
|
2017-09-24 05:18:20 +00:00
|
|
|
List<Pattern> wildcards = this.wildcards = new ArrayList<>();
|
|
|
|
List<HostRange> ranges = this.ranges = new ArrayList<>();
|
2017-06-11 20:40:08 +00:00
|
|
|
|
|
|
|
for( String filter : filters )
|
|
|
|
{
|
|
|
|
int cidr = filter.indexOf( '/' );
|
|
|
|
if( cidr >= 0 )
|
|
|
|
{
|
|
|
|
String addressStr = filter.substring( 0, cidr );
|
|
|
|
String prefixSizeStr = filter.substring( cidr + 1 );
|
|
|
|
|
|
|
|
int prefixSize;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
prefixSize = Integer.parseInt( prefixSizeStr );
|
|
|
|
}
|
|
|
|
catch( NumberFormatException e )
|
|
|
|
{
|
2019-03-10 11:22:11 +00:00
|
|
|
ComputerCraft.log.error(
|
|
|
|
"Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.",
|
|
|
|
filter, prefixSizeStr
|
|
|
|
);
|
2017-06-11 20:40:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
InetAddress address;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
address = InetAddresses.forString( addressStr );
|
|
|
|
}
|
|
|
|
catch( IllegalArgumentException e )
|
|
|
|
{
|
2019-03-10 11:22:11 +00:00
|
|
|
ComputerCraft.log.error(
|
|
|
|
"Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.",
|
|
|
|
filter, prefixSizeStr
|
|
|
|
);
|
2017-06-11 20:40:08 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mask the bytes of the IP address.
|
|
|
|
byte[] minBytes = address.getAddress(), maxBytes = address.getAddress();
|
|
|
|
int size = prefixSize;
|
|
|
|
for( int i = 0; i < minBytes.length; i++ )
|
|
|
|
{
|
|
|
|
if( size <= 0 )
|
|
|
|
{
|
2018-12-23 17:46:58 +00:00
|
|
|
minBytes[i] &= 0;
|
|
|
|
maxBytes[i] |= 0xFF;
|
2017-06-11 20:40:08 +00:00
|
|
|
}
|
|
|
|
else if( size < 8 )
|
|
|
|
{
|
2018-12-23 17:46:58 +00:00
|
|
|
minBytes[i] &= 0xFF << (8 - size);
|
|
|
|
maxBytes[i] |= ~(0xFF << (8 - size));
|
2017-06-11 20:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size -= 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
ranges.add( new HostRange( minBytes, maxBytes ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
wildcards.add( Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether a host name matches a series of patterns.
|
|
|
|
*
|
|
|
|
* This is intended to allow early exiting, before one has to look up the IP address. You should use
|
|
|
|
* {@link #matches(InetAddress)} instead of/in addition to this one.
|
|
|
|
*
|
|
|
|
* @param domain The domain to match.
|
|
|
|
* @return Whether the patterns were matched.
|
|
|
|
*/
|
|
|
|
public boolean matches( String domain )
|
|
|
|
{
|
|
|
|
for( Pattern domainPattern : wildcards )
|
|
|
|
{
|
|
|
|
if( domainPattern.matcher( domain ).matches() ) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean matchesAddress( InetAddress address )
|
|
|
|
{
|
|
|
|
String addressString = address.getHostAddress();
|
|
|
|
for( Pattern domainPattern : wildcards )
|
|
|
|
{
|
|
|
|
if( domainPattern.matcher( addressString ).matches() ) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( HostRange range : ranges )
|
|
|
|
{
|
|
|
|
if( range.contains( address ) ) return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether the given address matches a series of patterns
|
|
|
|
*
|
|
|
|
* @param address The address to check.
|
|
|
|
* @return Whether it matches any of these patterns.
|
|
|
|
*/
|
|
|
|
public boolean matches( InetAddress address )
|
|
|
|
{
|
|
|
|
// Match the host name
|
|
|
|
String host = address.getHostName();
|
|
|
|
if( host != null && matches( host ) ) return true;
|
|
|
|
|
|
|
|
// Match the normal address
|
|
|
|
if( matchesAddress( address ) ) return true;
|
|
|
|
|
|
|
|
// If we're an IPv4 address in disguise then let's check that.
|
2018-12-29 16:42:02 +00:00
|
|
|
return address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
|
|
|
|
&& matchesAddress( InetAddresses.get6to4IPv4Address( (Inet6Address) address ) );
|
2017-06-11 20:40:08 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|