directory-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Emmanuel Lecharny (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (DIRSERVER-2127) Don't rely on sun.net.util since it is not visible in OSGi.
Date Tue, 01 Mar 2016 22:55:18 GMT

    [ https://issues.apache.org/jira/browse/DIRSERVER-2127?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15174565#comment-15174565
] 

Emmanuel Lecharny commented on DIRSERVER-2127:
----------------------------------------------

Thanks Cristian, 

I'm actually considering injecting the {{isValidInet6Address}} part of commons.validator into
ApacheDS, instead of adding a new dependency to the project. That would basically solve the
issue the same way.

The patch would become :

{noformat}
### Eclipse Workspace Patch 1.0
#P api-ldap-model
Index: src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
===================================================================
--- src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java	(revision 1732336)
+++ src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java	(working copy)
@@ -23,6 +23,7 @@
 import java.io.ByteArrayOutputStream;
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -137,7 +138,7 @@
 
     /** modal parameter that forces explicit scope rendering in toString */
     private boolean forceScopeRendering;
-    
+
     /** The type of host we use */
     private HostTypeEnum hostType = HostTypeEnum.REGULAR_NAME;
 
@@ -377,46 +378,100 @@
         // elements.
         switch ( chars[pos] )
         {
-            case '[' :
+            case '[':
                 // This is an IP Literal address
                 return parseIpLiteral( chars, pos + 1 );
-                
-            case '0' :
-            case '1' :
-            case '2' :
-            case '3' :
-            case '4' :
-            case '5' :
-            case '6' :
-            case '7' :
-            case '8' :
-            case '9' :
+
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
                 // Probably an IPV4 address, but may be a reg-name
                 // try to parse an IPV4 address first
                 int currentPos = parseIPV4( chars, pos );
-                
+
                 if ( currentPos != -1 )
                 {
                     host = new String( chars, start, currentPos - start );
-                    
+
                     return currentPos;
                 }
                 //fallback to reg-name
-                
-            case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
-            case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
-            case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
-            case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
-            case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
-            case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
-            case 'p' : case 'q' : case 'r' : case 's' : case 't' :
-            case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
-            case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
-            case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
-            case 'z' : case 'Z' : case '-' : case '.' : case '_' :
-            case '~' : case '%' : case '!' : case '$' : case '&' :
-            case '\'' : case '(' : case ')' : case '*' : case '+' :
-            case ',' : case ';' : case '=' :
+
+            case 'a':
+            case 'b':
+            case 'c':
+            case 'd':
+            case 'e':
+            case 'A':
+            case 'B':
+            case 'C':
+            case 'D':
+            case 'E':
+            case 'f':
+            case 'g':
+            case 'h':
+            case 'i':
+            case 'j':
+            case 'F':
+            case 'G':
+            case 'H':
+            case 'I':
+            case 'J':
+            case 'k':
+            case 'l':
+            case 'm':
+            case 'n':
+            case 'o':
+            case 'K':
+            case 'L':
+            case 'M':
+            case 'N':
+            case 'O':
+            case 'p':
+            case 'q':
+            case 'r':
+            case 's':
+            case 't':
+            case 'P':
+            case 'Q':
+            case 'R':
+            case 'S':
+            case 'T':
+            case 'u':
+            case 'v':
+            case 'w':
+            case 'x':
+            case 'y':
+            case 'U':
+            case 'V':
+            case 'W':
+            case 'X':
+            case 'Y':
+            case 'z':
+            case 'Z':
+            case '-':
+            case '.':
+            case '_':
+            case '~':
+            case '%':
+            case '!':
+            case '$':
+            case '&':
+            case '\'':
+            case '(':
+            case ')':
+            case '*':
+            case '+':
+            case ',':
+            case ';':
+            case '=':
                 // A reg-name
                 return parseRegName( chars, pos );
 
@@ -423,13 +478,13 @@
             default:
                 break;
         }
-        
+
         host = new String( chars, start, pos - start );
 
         return pos;
     }
-    
-    
+
+
     /**
      * parse these rules :
      * <pre>
@@ -450,21 +505,21 @@
     private int parseIpLiteral( char[] chars, int pos )
     {
         int start = pos;
-        
+
         if ( Chars.isCharASCII( chars, pos, 'v' ) )
         {
             // This is an IPvFuture
             pos++;
             hostType = HostTypeEnum.IPV_FUTURE;
-            
+
             pos = parseIPvFuture( chars, pos );
-            
+
             if ( pos != -1 )
             {
                 // We don't keep the last char, which is a ']'
                 host = new String( chars, start, pos - start - 1 );
             }
-            
+
             return pos;
         }
         else
@@ -475,9 +530,145 @@
             return parseIPV6( chars, pos );
         }
     }
-    
-    
+
+
     /**
+     * Validates an IPv4 address. Returns true if valid.
+     * @param inet4Address the IPv4 address to validate
+     * @return true if the argument contains a valid IPv4 address
+     */
+    public boolean isValidInet4Address( String inet4Address )
+    {
+        return parseIPV4( inet4Address.toCharArray(), 0 ) != -1;
+    }
+
+
+    /**
+     * This code source was taken from commons.validator 1.5.0
+     * 
+     * Validates an IPv6 address. Returns true if valid.
+     * @param inet6Address the IPv6 address to validate
+     * @return true if the argument contains a valid IPv6 address
+     * 
+     * @since 1.4.1
+     */
+    public boolean isValidInet6Address( String inet6Address )
+    {
+        boolean containsCompressedZeroes = inet6Address.contains( "::" );
+
+        if ( containsCompressedZeroes && ( inet6Address.indexOf( "::" ) != inet6Address.lastIndexOf(
"::" ) ) )
+        {
+            return false;
+        }
+
+        if ( ( inet6Address.startsWith( ":" ) && !inet6Address.startsWith( "::" )
)
+            || ( inet6Address.endsWith( ":" ) && !inet6Address.endsWith( "::" ) )
)
+        {
+            return false;
+        }
+
+        String[] octets = inet6Address.split( ":" );
+
+        if ( containsCompressedZeroes )
+        {
+            List<String> octetList = new ArrayList<String>( Arrays.asList( octets
) );
+
+            if ( inet6Address.endsWith( "::" ) )
+            {
+                // String.split() drops ending empty segments
+                octetList.add( "" );
+            }
+            else if ( inet6Address.startsWith( "::" ) && !octetList.isEmpty() )
+            {
+                octetList.remove( 0 );
+            }
+
+            octets = octetList.toArray( new String[octetList.size()] );
+        }
+
+        if ( octets.length > 8 )
+        {
+            return false;
+        }
+
+        int validOctets = 0;
+        int emptyOctets = 0;
+
+        for ( int index = 0; index < octets.length; index++ )
+        {
+            String octet = ( String ) octets[index];
+
+            if ( octet.length() == 0 )
+            {
+                emptyOctets++;
+
+                if ( emptyOctets > 1 )
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                emptyOctets = 0;
+
+                if ( octet.contains( "." ) )
+                { // contains is Java 1.5+
+                    if ( !inet6Address.endsWith( octet ) )
+                    {
+                        return false;
+                    }
+
+                    if ( index > octets.length - 1 || index > 6 )
+                    {
+                        // IPV4 occupies last two octets
+                        return false;
+                    }
+
+                    if ( !isValidInet4Address( octet ) )
+                    {
+                        return false;
+                    }
+
+                    validOctets += 2;
+
+                    continue;
+                }
+
+                if ( octet.length() > 4 )
+                {
+                    return false;
+                }
+
+                int octetInt = 0;
+
+                try
+                {
+                    octetInt = Integer.valueOf( octet, 16 ).intValue();
+                }
+                catch ( NumberFormatException e )
+                {
+                    return false;
+                }
+
+                if ( octetInt < 0 || octetInt > 0xffff )
+                {
+                    return false;
+                }
+            }
+
+            validOctets++;
+        }
+
+        if ( validOctets < 8 && !containsCompressedZeroes )
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
      * Parse the following rules :
      * <pre>
      * IPv6address = 6( h16 ":" ) ls32 
@@ -506,12 +697,12 @@
         if ( Chars.isCharASCII( chars, pos, ']' ) )
         {
             String hostString = new String( chars, start, pos - start );
-            
-            if ( sun.net.util.IPAddressUtil.isIPv6LiteralAddress( hostString ) )
+
+            if ( isValidInet6Address( hostString ) )
             {
                 host = hostString;
-                
-                return  pos + 1;
+
+                return pos + 1;
             }
             else
             {
@@ -518,11 +709,11 @@
                 return -1;
             }
         }
-        
+
         return -1;
     }
-    
 
+
     /**
      * Parse these rules :
      * <pre>
@@ -534,78 +725,138 @@
     {
         // We should have at least one hex digit
         boolean hexFound = false;
-        
+
         while ( Chars.isHex( chars, pos ) )
         {
             hexFound = true;
             pos++;
         }
-        
+
         if ( !hexFound )
         {
             return -1;
         }
-        
+
         // a dot is expected
         if ( !Chars.isCharASCII( chars, pos, '.' ) )
         {
             return -1;
         }
-        
+
         // Now, we should have at least one char in unreserved / sub-delims / ":"
         boolean valueFound = false;
-        
+
         while ( !Chars.isCharASCII( chars, pos, ']' ) )
         {
             switch ( chars[pos] )
             {
-                // Unserserved
-                // ALPHA
-                case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
-                case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
-                case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
-                case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
-                case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
-                case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
-                case 'p' : case 'q' : case 'r' : case 's' : case 't' :
-                case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
-                case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
-                case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
-                case 'z' : case 'Z' : 
-                    
-                // DIGITs
-                case '0' : case '1' : case '2' : case '3' : case '4' : 
-                case '5' : case '6' : case '7' : case '8' : case '9' :
-                    
-                // others
-                case '-' : case '.' : case '_' : case '~' :  
-                
-                // sub-delims
-                case '!' : case '$' : case '&' : case '\'' : 
-                case '(' : case ')' : case '*' : case '+' : case ',' : 
-                case ';' : case '=' :
-                    
-                // Special case for ':'
-                case ':' :
+            // Unserserved
+            // ALPHA
+                case 'a':
+                case 'b':
+                case 'c':
+                case 'd':
+                case 'e':
+                case 'A':
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'E':
+                case 'f':
+                case 'g':
+                case 'h':
+                case 'i':
+                case 'j':
+                case 'F':
+                case 'G':
+                case 'H':
+                case 'I':
+                case 'J':
+                case 'k':
+                case 'l':
+                case 'm':
+                case 'n':
+                case 'o':
+                case 'K':
+                case 'L':
+                case 'M':
+                case 'N':
+                case 'O':
+                case 'p':
+                case 'q':
+                case 'r':
+                case 's':
+                case 't':
+                case 'P':
+                case 'Q':
+                case 'R':
+                case 'S':
+                case 'T':
+                case 'u':
+                case 'v':
+                case 'w':
+                case 'x':
+                case 'y':
+                case 'U':
+                case 'V':
+                case 'W':
+                case 'X':
+                case 'Y':
+                case 'z':
+                case 'Z':
+
+                    // DIGITs
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+
+                    // others
+                case '-':
+                case '.':
+                case '_':
+                case '~':
+
+                    // sub-delims
+                case '!':
+                case '$':
+                case '&':
+                case '\'':
+                case '(':
+                case ')':
+                case '*':
+                case '+':
+                case ',':
+                case ';':
+                case '=':
+
+                    // Special case for ':'
+                case ':':
                     pos++;
                     valueFound = true;
                     break;
-                    
-                default :
+
+                default:
                     // Wrong char
                     return -1;
             }
         }
-        
+
         if ( !valueFound )
         {
             return -1;
         }
-        
+
         return pos;
     }
-    
-    
+
+
     /**
      * parse these rules :
      * <pre>
@@ -619,41 +870,101 @@
     private int parseRegName( char[] chars, int pos )
     {
         int start = pos;
-        
+
         while ( !Chars.isCharASCII( chars, pos, ':' ) && !Chars.isCharASCII( chars,
pos, '/' ) && ( pos < chars.length ) )
         {
             switch ( chars[pos] )
             {
-                // Unserserved
-                // ALPHA
-                case 'a' : case 'b' : case 'c' : case 'd' : case 'e' :
-                case 'A' : case 'B' : case 'C' : case 'D' : case 'E' :
-                case 'f' : case 'g' : case 'h' : case 'i' : case 'j' :
-                case 'F' : case 'G' : case 'H' : case 'I' : case 'J' :
-                case 'k' : case 'l' : case 'm' : case 'n' : case 'o' :
-                case 'K' : case 'L' : case 'M' : case 'N' : case 'O' :
-                case 'p' : case 'q' : case 'r' : case 's' : case 't' :
-                case 'P' : case 'Q' : case 'R' : case 'S' : case 'T' :
-                case 'u' : case 'v' : case 'w' : case 'x' : case 'y' :
-                case 'U' : case 'V' : case 'W' : case 'X' : case 'Y' :
-                case 'z' : case 'Z' : 
-                    
-                // DIGITs
-                case '0' : case '1' : case '2' : case '3' : case '4' : 
-                case '5' : case '6' : case '7' : case '8' : case '9' :
-                    
-                // others
-                case '-' : case '.' : case '_' : case '~' :  
-                
-                // sub-delims
-                case '!' : case '$' : case '&' : case '\'' : 
-                case '(' : case ')' : case '*' : case '+' : case ',' : 
-                case ';' : case '=' :
+            // Unserserved
+            // ALPHA
+                case 'a':
+                case 'b':
+                case 'c':
+                case 'd':
+                case 'e':
+                case 'A':
+                case 'B':
+                case 'C':
+                case 'D':
+                case 'E':
+                case 'f':
+                case 'g':
+                case 'h':
+                case 'i':
+                case 'j':
+                case 'F':
+                case 'G':
+                case 'H':
+                case 'I':
+                case 'J':
+                case 'k':
+                case 'l':
+                case 'm':
+                case 'n':
+                case 'o':
+                case 'K':
+                case 'L':
+                case 'M':
+                case 'N':
+                case 'O':
+                case 'p':
+                case 'q':
+                case 'r':
+                case 's':
+                case 't':
+                case 'P':
+                case 'Q':
+                case 'R':
+                case 'S':
+                case 'T':
+                case 'u':
+                case 'v':
+                case 'w':
+                case 'x':
+                case 'y':
+                case 'U':
+                case 'V':
+                case 'W':
+                case 'X':
+                case 'Y':
+                case 'z':
+                case 'Z':
+
+                    // DIGITs
+                case '0':
+                case '1':
+                case '2':
+                case '3':
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+
+                    // others
+                case '-':
+                case '.':
+                case '_':
+                case '~':
+
+                    // sub-delims
+                case '!':
+                case '$':
+                case '&':
+                case '\'':
+                case '(':
+                case ')':
+                case '*':
+                case '+':
+                case ',':
+                case ';':
+                case '=':
                     pos++;
                     break;
-                    
+
                 // pct-encoded
-                case '%' : 
+                case '%':
                     if ( Chars.isHex( chars, pos + 1 ) && Chars.isHex( chars, pos
+ 2 ) )
                     {
                         pos += 3;
@@ -662,20 +973,20 @@
                     {
                         return -1;
                     }
-                    
-                default :
+
+                default:
                     // Wrong char
                     return -1;
             }
         }
-        
+
         host = new String( chars, start, pos - start );
         hostType = HostTypeEnum.REGULAR_NAME;
-        
+
         return pos;
     }
 
-    
+
     /**
      * Parse these rules :
      * <pre>
@@ -696,13 +1007,13 @@
         for ( int i = 0; i < 3; i++ )
         {
             ipPos = parseDecOctet( chars, ipPos, ipElem, i );
-            
+
             if ( ipPos == -1 )
             {
                 // Not an IPV4 address
                 return -1;
             }
-            
+
             if ( chars[ipPos] != '.' )
             {
                 // Not an IPV4 address
@@ -715,7 +1026,7 @@
         }
 
         ipPos = parseDecOctet( chars, ipPos, ipElem, 3 );
-        
+
         if ( ipPos == -1 )
         {
             // Not an IPV4 address
@@ -726,12 +1037,12 @@
             pos = ipPos;
             host = new String( chars, start, pos - start );
             hostType = HostTypeEnum.IPV4;
-            
+
             return pos;
         }
     }
-    
-    
+
+
     /**
      * Parse this rule :
      * <pre>
@@ -743,18 +1054,18 @@
         int ipElemValue = 0;
         boolean ipElemSeen = false;
         boolean hasTailingZeroes = false;
-        
+
         while ( Chars.isDigit( chars, pos ) )
         {
             ipElemSeen = true;
             ipElemValue = ( ipElemValue * 10 ) + ( chars[pos] - '0' );
-            
+
             if ( ( chars[pos] == '0' ) && hasTailingZeroes && ( ipElemValue
> 0 ) )
             {
                 // Two 0 at the beginning : not allowed
                 return -1;
             }
-            
+
             if ( ipElemValue > 255 )
             {
                 // We don't allow IPV4 address with values > 255
@@ -763,11 +1074,11 @@
 
             pos++;
         }
-        
+
         if ( ipElemSeen )
         {
             ipElem[octetNb] = ipElemValue;
-            
+
             return pos;
         }
         else
@@ -775,8 +1086,8 @@
             return -1;
         }
     }
-    
 
+
     /**
      * Parse this rule : <br>
      * <pre>
@@ -922,7 +1233,7 @@
                 }
                 catch ( ArrayIndexOutOfBoundsException aioobe )
                 {
-                    throw new UrlDecoderException( I18n.err( I18n.ERR_04414 ) , aioobe );
+                    throw new UrlDecoderException( I18n.err( I18n.ERR_04414 ), aioobe );
                 }
             }
             else
@@ -1591,13 +1902,13 @@
         {
             switch ( hostType )
             {
-                case IPV4 :
-                case REGULAR_NAME :
+                case IPV4:
+                case REGULAR_NAME:
                     sb.append( host );
                     break;
-                    
-                case IPV6 :
-                case IPV_FUTURE :
+
+                case IPV6:
+                case IPV_FUTURE:
                     sb.append( '[' ).append( host ).append( ']' );
                     break;

{noformat}

wdyt ?

And thanks for the proposed fix btw !

> Don't rely on sun.net.util since it is not visible in OSGi.
> -----------------------------------------------------------
>
>                 Key: DIRSERVER-2127
>                 URL: https://issues.apache.org/jira/browse/DIRSERVER-2127
>             Project: Directory ApacheDS
>          Issue Type: Bug
>    Affects Versions: 2.0.0-M21
>            Reporter: Cristian Tarsoaga
>            Priority: Minor
>              Labels: osgi,
>         Attachments: 0001-Use-a-better-IPv6-address-parser.patch
>
>
> From ee47e87b6d3e88d411220ccce43d8feecf4e5dec Mon Sep 17 00:00:00 2001
> From: Ciprian Ciubotariu <cheepeero@gmx.net>
> Date: Sat, 27 Feb 2016 01:35:22 +0200
> Subject: [PATCH] Use a better IPv6 address parser
> Don't rely on sun.net.util since it is not visible in OSGi.
> ---
>  ldap/model/pom.xml                                                   | 5 +++++
>  .../main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java   | 3 ++-
>  2 files changed, 7 insertions(+), 1 deletion(-)
> diff --git a/ldap/model/pom.xml b/ldap/model/pom.xml
> index fc4c4a9..a370828 100644
> --- a/ldap/model/pom.xml
> +++ b/ldap/model/pom.xml
> @@ -96,6 +96,11 @@
>        <artifactId>annotations</artifactId>
>        <scope>provided</scope>
>      </dependency>
> +    <dependency>
> +      <groupId>commons-validator</groupId>
> +      <artifactId>commons-validator</artifactId>
> +      <version>1.5.0</version>
> +    </dependency>
>    </dependencies>
>  
>    <build>
> diff --git a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
> index 8811139..716e862 100644
> --- a/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
> +++ b/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
> @@ -28,6 +28,7 @@ import java.util.List;
>  import java.util.Set;
>  import java.util.regex.Matcher;
>  import java.util.regex.Pattern;
> +import org.apache.commons.validator.routines.InetAddressValidator;
>  
>  import org.apache.directory.api.i18n.I18n;
>  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
> @@ -507,7 +508,7 @@ public class LdapUrl
>          {
>              String hostString = new String( chars, start, pos - start );
>              
> -            if ( sun.net.util.IPAddressUtil.isIPv6LiteralAddress( hostString ) )
> +            if ( InetAddressValidator.getInstance().isValidInet6Address( hostString
) )
>              {
>                  host = hostString;
>                  
> -- 
> 2.4.10



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message