@@ -99,41 +99,9 @@ public Value evaluate(List<Value> arguments) {
9999 return Value .emptyValue ();
100100 }
101101
102- boolean isIpAddr = false ;
103- String host = parsed .getHost ();
104- if (host .startsWith ("[" ) && host .endsWith ("]" )) {
105- isIpAddr = true ;
106- }
107- String [] dottedParts = host .split ("\\ ." );
108- if (dottedParts .length == 4 ) {
109- isIpAddr = true ;
110- for (String dottedPart : dottedParts ) {
111- try {
112- int value = Integer .parseInt (dottedPart );
113- if (value < 0 || value > 255 ) {
114- isIpAddr = false ;
115- }
116- } catch (NumberFormatException ex ) {
117- isIpAddr = false ;
118- }
119- }
120- }
121-
102+ boolean isIpAddr = isIpAddr (parsed .getHost ());
122103 String path = parsed .getPath ();
123- String normalizedPath ;
124- if (StringUtils .isBlank (path )) {
125- normalizedPath = "/" ;
126- } else {
127- StringBuilder builder = new StringBuilder ();
128- if (!path .startsWith ("/" )) {
129- builder .append ("/" );
130- }
131- builder .append (path );
132- if (!path .endsWith ("/" )) {
133- builder .append ("/" );
134- }
135- normalizedPath = builder .toString ();
136- }
104+ String normalizedPath = normalizePath (path );
137105
138106 Map <Identifier , Value > values = new LinkedHashMap <>();
139107 values .put (SCHEME , Value .stringValue (parsed .getProtocol ()));
@@ -152,4 +120,92 @@ public ParseUrl createFunction(FunctionNode functionNode) {
152120 return new ParseUrl (functionNode );
153121 }
154122 }
123+
124+ /**
125+ * Checks if a host is an IP address for use with endpoint rules.
126+ *
127+ * @param host Host to check.
128+ * @return true if it is an IP address.
129+ */
130+ public static boolean isIpAddr (String host ) {
131+ if (host == null || host .length () < 2 ) {
132+ return false ;
133+ }
134+
135+ // Simple check for IPv6 (enclosed in square brackets)
136+ if (host .charAt (0 ) == '[' && host .charAt (host .length () - 1 ) == ']' ) {
137+ return true ;
138+ }
139+
140+ int from = 0 ;
141+ int segments = 0 ;
142+ boolean done = false ;
143+ while (!done ) {
144+ int index = host .indexOf ('.' , from );
145+ if (index == -1 ) {
146+ if (segments != 3 ) {
147+ // E.g., 123.com
148+ return false ;
149+ }
150+ index = host .length ();
151+ done = true ;
152+ } else if (segments == 3 ) {
153+ // E.g., 1.2.3.4.5
154+ return false ;
155+ }
156+ int length = index - from ;
157+ if (length == 1 ) {
158+ char ch0 = host .charAt (from );
159+ if (ch0 < '0' || ch0 > '9' ) {
160+ return false ;
161+ }
162+ } else if (length == 2 ) {
163+ char ch0 = host .charAt (from );
164+ char ch1 = host .charAt (from + 1 );
165+ if ((ch0 <= '0' || ch0 > '9' ) || (ch1 < '0' || ch1 > '9' )) {
166+ return false ;
167+ }
168+ } else if (length == 3 ) {
169+ char ch0 = host .charAt (from );
170+ char ch1 = host .charAt (from + 1 );
171+ char ch2 = host .charAt (from + 2 );
172+ if ((ch0 <= '0' || ch0 > '9' )
173+ || (ch1 < '0' || ch1 > '9' )
174+ || (ch2 < '0' || ch2 > '9' )) {
175+ return false ;
176+ }
177+ int value = ((ch0 - '0' ) * 100 ) + ((ch1 - '0' ) * 10 ) + (ch2 - '0' );
178+ if (value > 255 ) {
179+ return false ;
180+ }
181+ } else {
182+ return false ;
183+ }
184+ from = index + 1 ;
185+ segments += 1 ;
186+ }
187+ return true ;
188+ }
189+
190+ /**
191+ * Normalizes a path string according to the ParseURL function.
192+ *
193+ * @param path Path string to normalize.
194+ * @return the normalized path.
195+ */
196+ public static String normalizePath (String path ) {
197+ if (StringUtils .isBlank (path )) {
198+ return "/" ;
199+ } else {
200+ StringBuilder builder = new StringBuilder ();
201+ if (!path .startsWith ("/" )) {
202+ builder .append ("/" );
203+ }
204+ builder .append (path );
205+ if (!path .endsWith ("/" )) {
206+ builder .append ("/" );
207+ }
208+ return builder .toString ();
209+ }
210+ }
155211}
0 commit comments