diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/FilterLibrary.java b/src/main/java/com/hubspot/jinjava/lib/filter/FilterLibrary.java index c28d60d00..1d86e7948 100644 --- a/src/main/java/com/hubspot/jinjava/lib/filter/FilterLibrary.java +++ b/src/main/java/com/hubspot/jinjava/lib/filter/FilterLibrary.java @@ -74,6 +74,7 @@ protected void registerDefaults() { ReverseFilter.class, RoundFilter.class, SumFilter.class, + IpAddrFilter.class, EscapeFilter.class, EAliasedEscapeFilter.class, diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/IpAddrFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/IpAddrFilter.java new file mode 100644 index 000000000..cf4cb92cd --- /dev/null +++ b/src/main/java/com/hubspot/jinjava/lib/filter/IpAddrFilter.java @@ -0,0 +1,50 @@ +package com.hubspot.jinjava.lib.filter; + +import java.util.regex.Pattern; + +import com.hubspot.jinjava.doc.annotations.JinjavaDoc; +import com.hubspot.jinjava.doc.annotations.JinjavaParam; +import com.hubspot.jinjava.doc.annotations.JinjavaSnippet; +import com.hubspot.jinjava.interpret.JinjavaInterpreter; + +@JinjavaDoc( + value = "Evaluates to true if the value is a valid IPv4 or IPv6 address", + params = { + @JinjavaParam(value = "value", type = "string", desc = "String to check IP Address"), + }, + snippets = { + @JinjavaSnippet( + desc = "This example shows how to test if a string is a valid ip address", + code = "{% set ip = '1.0.0.1' %}\n" + + "{% if ip|ipaddr %}\n" + + " The string is a valid IP address\n" + + "{% endif %}") + }) +public class IpAddrFilter implements Filter { + + private static final Pattern IP4_PATTERN = Pattern.compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])"); + private static final Pattern IP6_PATTERN = Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$"); + private static final Pattern IP6_COMPRESSED_PATTERN = Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$"); + + @Override + public Object filter(Object object, JinjavaInterpreter interpreter, String... arg) { + + if (object == null) { + return false; + } + + if (object instanceof String) { + String address = ((String) object).trim(); + return IP4_PATTERN.matcher(address).matches() + || IP6_PATTERN.matcher(address).matches() + || IP6_COMPRESSED_PATTERN.matcher(address).matches(); + } + return false; + } + + @Override + public String getName() { + return "ipaddr"; + } + +} diff --git a/src/test/java/com/hubspot/jinjava/lib/filter/IpAddrFilterTest.java b/src/test/java/com/hubspot/jinjava/lib/filter/IpAddrFilterTest.java new file mode 100644 index 000000000..a219d0852 --- /dev/null +++ b/src/test/java/com/hubspot/jinjava/lib/filter/IpAddrFilterTest.java @@ -0,0 +1,54 @@ +package com.hubspot.jinjava.lib.filter; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.Before; +import org.junit.Test; + +import com.hubspot.jinjava.Jinjava; +import com.hubspot.jinjava.interpret.JinjavaInterpreter; + +public class IpAddrFilterTest { + + private IpAddrFilter ipAddrFilter; + private JinjavaInterpreter interpreter; + + @Before + public void setup() { + ipAddrFilter = new IpAddrFilter(); + interpreter = new Jinjava().newInterpreter(); + } + + @Test + public void itAcceptsValidIpV4Address() { + assertThat(ipAddrFilter.filter("255.182.100.1", interpreter)).isEqualTo(true); + assertThat(ipAddrFilter.filter("125.0.100.1", interpreter)).isEqualTo(true); + assertThat(ipAddrFilter.filter("128.0.0.1", interpreter)).isEqualTo(true); + assertThat(ipAddrFilter.filter(" 128.0.0.1 ", interpreter)).isEqualTo(true); + } + + @Test + public void itRejectsInvalidIpV4Address() { + assertThat(ipAddrFilter.filter("255.182.100.abc", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("125.512.100.1", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("125.512.100.1.1", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("125.512.100", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter(104, interpreter)).isEqualTo(false); + } + + @Test + public void itAcceptsValidIpV6Address() { + assertThat(ipAddrFilter.filter("1200:0000:AB00:1234:0000:2552:7777:1313", interpreter)).isEqualTo(true); + assertThat(ipAddrFilter.filter("21DA:D3:0:2F3B:2AA:FF:FE28:9C5A", interpreter)).isEqualTo(true); + assertThat(ipAddrFilter.filter("2000::", interpreter)).isEqualTo(true); + } + + @Test + public void itRejectsInvalidIpV6Address() { + assertThat(ipAddrFilter.filter("1200::AB00:1234::2552:7777:1313", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("1200:0000:AB00:1234:O000:2552:7777:1313", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("1200::AB00:1234::2552:7777:1313:1232", interpreter)).isEqualTo(false); + assertThat(ipAddrFilter.filter("321", interpreter)).isEqualTo(false); + } + +}