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" ) ); + } + +}
