This is an automated email from the ASF dual-hosted git repository.

juanpablo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jspwiki.git

commit e68871423703b8db67a236ea4a931e4d01a9b396
Author: juanpablo <[email protected]>
AuthorDate: Wed Mar 4 20:17:28 2020 +0100

    move isIPV4Address( String ) method from WikiSession to HttpUtil
---
 .../main/java/org/apache/wiki/util/HttpUtil.java   | 126 ++++++++++++---------
 .../java/org/apache/wiki/util/HttpUtilTest.java    |  50 ++++++++
 2 files changed, 123 insertions(+), 53 deletions(-)

diff --git a/jspwiki-util/src/main/java/org/apache/wiki/util/HttpUtil.java 
b/jspwiki-util/src/main/java/org/apache/wiki/util/HttpUtil.java
index 3cd7f5d..7ad7399 100644
--- a/jspwiki-util/src/main/java/org/apache/wiki/util/HttpUtil.java
+++ b/jspwiki-util/src/main/java/org/apache/wiki/util/HttpUtil.java
@@ -38,7 +38,10 @@ import java.util.Date;
  */
 public final class HttpUtil {
 
-    static Logger log = Logger.getLogger( HttpUtil.class );
+    private static final Logger log = Logger.getLogger( HttpUtil.class );
+    private static final int    ONE                   = 48;
+    private static final int    NINE                  = 57;
+    private static final int    DOT                   = 46;
     
     /** Private constructor to prevent direct instantiation. */
     private HttpUtil() {
@@ -51,29 +54,27 @@ public final class HttpUtil {
      * @param req http request
      * @return remote address associated to the request.
      */
-    public static String getRemoteAddress( HttpServletRequest req ) {
+    public static String getRemoteAddress( final HttpServletRequest req ) {
                return StringUtils.isNotEmpty ( req.getHeader( 
"X-Forwarded-For" ) ) ? req.getHeader( "X-Forwarded-For" ) : 
-                                                                               
           req.getRemoteAddr();
+                                                                               
                  req.getRemoteAddr();
        }
 
     /**
-     *  Attempts to retrieve the given cookie value from the request.
-     *  Returns the string value (which may or may not be decoded
-     *  correctly, depending on browser!), or null if the cookie is
-     *  not found. The algorithm will automatically trim leading
+     *  Attempts to retrieve the given cookie value from the request. Returns 
the string value (which may or may not be decoded
+     *  correctly, depending on browser!), or null if the cookie is not found. 
The algorithm will automatically trim leading
      *  and trailing double quotes, if found.
      *
      *  @param request The current request
      *  @param cookieName The name of the cookie to fetch.
      *  @return Value of the cookie, or null, if there is no such cookie.
      */
-    public static String retrieveCookieValue( HttpServletRequest request, 
String cookieName ) {
-        Cookie[] cookies = request.getCookies();
+    public static String retrieveCookieValue( final HttpServletRequest 
request, final String cookieName ) {
+        final Cookie[] cookies = request.getCookies();
 
         if( cookies != null ) {
-            for( int i = 0; i < cookies.length; i++ ) {
-                if( cookies[i].getName().equals( cookieName ) ) {
-                    String value = cookies[i].getValue();
+            for( final Cookie cookie : cookies ) {
+                if( cookie.getName().equals( cookieName ) ) {
+                    String value = cookie.getValue();
                     if( value.length() == 0 ) {
                         return null;
                     }
@@ -89,83 +90,67 @@ public final class HttpUtil {
     }
 
     /**
-     *  Creates an ETag based on page information.  An ETag is unique to each 
page
-     *  and version, so it can be used to check if the page has changed.  Do 
not
-     *  assume that the ETag is in any particular format.
+     *  Creates an ETag based on page information. An ETag is unique to each 
page and version, so it can be used to check if the page has
+     *  changed. Do not assume that the ETag is in any particular format.
      *  
      *  @param pageName  The page name for which the ETag should be created.
      *  @param lastModified  The page last modified date for which the ETag 
should be created.
      *  @return A String depiction of an ETag.
      */
-    public static String createETag( String pageName, Date lastModified ) {
+    public static String createETag( final String pageName, final Date 
lastModified ) {
         return Long.toString( pageName.hashCode() ^ lastModified.getTime() );
     }
     
     /**
      *  If returns true, then should return a 304 (HTTP_NOT_MODIFIED)
+     *
      *  @param req the HTTP request
      *  @param pageName the wiki page name to check for
      *  @param lastModified the last modified date of the wiki page to check 
for
      *  @return the result of the check
      */
-    public static boolean checkFor304( HttpServletRequest req, String 
pageName, Date lastModified ) {
-        //
-        //  We'll do some handling for CONDITIONAL GET (and return a 304)
-        //  If the client has set the following headers, do not try for a 304.
-        //
+    public static boolean checkFor304( final HttpServletRequest req, final 
String pageName, final Date lastModified ) {
+        // We'll do some handling for CONDITIONAL GET (and return a 304). If 
the client has set the following headers, do not try for a 304.
         //    pragma: no-cache
         //    cache-control: no-cache
-        //
-
         if( "no-cache".equalsIgnoreCase( req.getHeader( "Pragma" ) )
             || "no-cache".equalsIgnoreCase( req.getHeader( "cache-control" ) ) 
) {
             // Wants specifically a fresh copy
         } else {
-            //
             //  HTTP 1.1 ETags go first
-            //
-            String thisTag = createETag( pageName, lastModified );
-                        
-            String eTag = req.getHeader( "If-None-Match" );
+            final String thisTag = createETag( pageName, lastModified );
+            final String eTag = req.getHeader( "If-None-Match" );
             
             if( eTag != null && eTag.equals(thisTag) ) {
                 return true;
             }
             
-            //
             //  Next, try if-modified-since
-            //
-            DateFormat rfcDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy 
HH:mm:ss z");
+            final DateFormat rfcDateFormat = new SimpleDateFormat( "EEE, dd 
MMM yyyy HH:mm:ss z" );
 
             try {
-                long ifModifiedSince = req.getDateHeader( "If-Modified-Since" 
);
+                final long ifModifiedSince = req.getDateHeader( 
"If-Modified-Since" );
 
-                //log.info("ifModifiedSince:"+ifModifiedSince);
                 if( ifModifiedSince != -1 ) {
-                    long lastModifiedTime = lastModified.getTime();
-
-                    //log.info("lastModifiedTime:" + lastModifiedTime);
+                    final long lastModifiedTime = lastModified.getTime();
                     if( lastModifiedTime <= ifModifiedSince ) {
                         return true;
                     }
                 } else {
                     try {
-                        String s = req.getHeader("If-Modified-Since");
-
+                        final String s = req.getHeader("If-Modified-Since");
                         if( s != null ) {
-                            Date ifModifiedSinceDate = rfcDateFormat.parse(s);
-                            //log.info("ifModifiedSinceDate:" + 
ifModifiedSinceDate);
-                            if( lastModified.before(ifModifiedSinceDate) ) {
+                            final Date ifModifiedSinceDate = 
rfcDateFormat.parse( s );
+                            if( lastModified.before( ifModifiedSinceDate ) ) {
                                 return true;
                             }
                         }
-                    } catch (ParseException e) {
-                        log.warn(e.getLocalizedMessage(), e);
+                    } catch( final ParseException e ) {
+                        log.warn( e.getLocalizedMessage(), e );
                     }
                 }
-            } catch( IllegalArgumentException e ) {
-                // Illegal date/time header format.
-                // We fail quietly, and return false.
+            } catch( final IllegalArgumentException e ) {
+                // Illegal date/time header format.  We fail quietly, and 
return false.
                 // FIXME: Should really move to ETags.
             }
         }
@@ -174,13 +159,12 @@ public final class HttpUtil {
     }
 
     /**
-     *  Attempts to form a valid URI based on the string given.  Currently
-     *  it can guess email addresses (mailto:).  If nothing else is given,
-     *  it assumes it to be an http:// url.
+     * Attempts to form a valid URI based on the string given.  Currently it 
can guess email addresses (mailto:).  If nothing else is given,
+     * it assumes it to be an http:// url.
      * 
-     *  @param uri  URI to take a poke at
-     *  @return Possibly a valid URI
-     *  @since 2.2.8
+     * @param uri  URI to take a poke at
+     * @return Possibly a valid URI
+     * @since 2.2.8
      */
     public static String guessValidURI( String uri ) {
         if( uri.indexOf( '@' ) != -1 ) {
@@ -204,7 +188,6 @@ public final class HttpUtil {
      *
      *  @param request The HTTP request to parse.
      *  @return The query string. If the query string is null, returns an 
empty string.
-     *
      *  @since 2.1.3 (method moved from WikiEngine on 2.11.0.M6)
      */
     public static String safeGetQueryString( final HttpServletRequest request, 
final Charset contentEncoding ) {
@@ -234,4 +217,41 @@ public final class HttpUtil {
         return res;
     }
 
+    /**
+     * Verifies whether a String represents an IPv4 address. The algorithm is 
extremely efficient and does not allocate any objects.
+     *
+     * @param name the address to test
+     * @return the result
+     */
+    public static boolean isIPV4Address( final String name ) {
+        if( StringUtils.isEmpty( name ) || name.charAt( 0 ) == DOT || 
name.charAt( name.length() - 1 ) == DOT ) {
+            return false;
+        }
+
+        final int[] addr = new int[] { 0, 0, 0, 0 };
+        int currentOctet = 0;
+        for( int i = 0; i < name.length(); i++ ) {
+            if( currentOctet > 3 ) {
+                return false;
+            }
+            final int ch = name.charAt( i );
+            final boolean isDigit = ch >= ONE && ch <= NINE;
+            final boolean isDot = ch == DOT;
+            if( !isDigit && !isDot ) {
+                return false;
+            }
+            if( isDigit ) {
+                addr[ currentOctet ] = 10 * addr[ currentOctet ] + ( ch - ONE 
);
+                if( addr[ currentOctet ] > 255 ) {
+                    return false;
+                }
+            } else if( name.charAt( i - 1 ) == DOT ) {
+                return false;
+            } else {
+                currentOctet++;
+            }
+        }
+        return currentOctet == 3;
+    }
+
 }
diff --git a/jspwiki-util/src/test/java/org/apache/wiki/util/HttpUtilTest.java 
b/jspwiki-util/src/test/java/org/apache/wiki/util/HttpUtilTest.java
new file mode 100644
index 0000000..28d02d4
--- /dev/null
+++ b/jspwiki-util/src/test/java/org/apache/wiki/util/HttpUtilTest.java
@@ -0,0 +1,50 @@
+/*
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+ */
+package org.apache.wiki.util;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+
+public class HttpUtilTest {
+
+    @Test
+    public void testIsIPV4Address() {
+        Assertions.assertFalse( HttpUtil.isIPV4Address( null ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( ".123.123.123.123" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "123.123.123.123." ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "123.123.123" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "123.123.123.123.123" 
) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "abc.123.123.123" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "Me" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "Guest" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "1207.0.0.1" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "127..0.1" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "1207.0.0." ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( ".0.0.1" ) );
+        Assertions.assertFalse( HttpUtil.isIPV4Address( "..." ) );
+
+        Assertions.assertTrue( HttpUtil.isIPV4Address( "127.0.0.1" ) );
+        Assertions.assertTrue( HttpUtil.isIPV4Address( "12.123.123.123" ) );
+        Assertions.assertTrue( HttpUtil.isIPV4Address( "012.123.123.123" ) );
+        Assertions.assertTrue( HttpUtil.isIPV4Address( "123.123.123.123" ) );
+    }
+
+}

Reply via email to