directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1602776 - in /directory/shared/trunk/ldap/model/src: main/java/org/apache/directory/api/ldap/model/url/ test/java/org/apache/directory/api/ldap/model/url/
Date Sun, 15 Jun 2014 23:00:36 GMT
Author: elecharny
Date: Sun Jun 15 23:00:36 2014
New Revision: 1602776

URL: http://svn.apache.org/r1602776
Log:
Added support for RFC 3986. Fix for DIRAPI-125

Added:
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
Modified:
    directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
    directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java

Added: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java?rev=1602776&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
(added)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/HostTypeEnum.java
Sun Jun 15 23:00:36 2014
@@ -0,0 +1,41 @@
+/*
+ *   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.directory.api.ldap.model.url;
+
+/**
+ * The type of Host we may have . One of :
+ * <ul>
+ * <li>IPV4 : IPV4 host</li>
+ * <li>IPV6 : IPV6 host</li>
+ * <li>IPV_FUTURE : IP v Future host</li>
+ * <li>REGULAR_NAME : A regular name</li>
+ * <li></li>
+ * </ul>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public enum HostTypeEnum
+{
+    IPV4,
+    IPV6,
+    IPV_FUTURE,
+    REGULAR_NAME
+}

Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java?rev=1602776&r1=1602775&r2=1602776&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
(original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/api/ldap/model/url/LdapUrl.java
Sun Jun 15 23:00:36 2014
@@ -43,27 +43,57 @@ import org.apache.directory.api.util.Str
 import org.apache.directory.api.util.Strings;
 import org.apache.directory.api.util.Unicode;
 
+import sun.net.util.IPAddressUtil;
+
 
 /**
  * Decodes a LdapUrl, and checks that it complies with
- * the RFC 2255. The grammar is the following :
+ * the RFC 4516. The grammar is the following :
  * <pre>
- * ldapurl    = scheme "://" [hostport] ["/"
- *                   [dn ["?" [attributes] ["?" [scope]
- *                   ["?" [filter] ["?" extensions]]]]]]
+ * ldapurl    = scheme "://" [host [ ":" port]] ["/"
+ *                   dn ["?" [attributes] ["?" [scope]
+ *                   ["?" [filter] ["?" extensions]]]]]
  * scheme     = "ldap"
- * attributes = attrdesc *("," attrdesc)
- * scope      = "base" / "one" / "sub"
  * dn         = Dn
- * hostport   = hostport from Section 5 of RFC 1738
- * attrdesc   = AttributeDescription from Section 4.1.5 of RFC 2251
- * filter     = filter from Section 4 of RFC 2254
- * extensions = extension *("," extension)
+ * attributes = attrdesc ["," attrdesc]*
+ * attrdesc   = selector ["," selector]*
+ * selector   = attributeSelector (from Section 4.5.1 of RFC4511)
+ * scope      = "base" / "one" / "sub"
+ * extensions = extension ["," extension]*
  * extension  = ["!"] extype ["=" exvalue]
- * extype     = token / xtoken
- * exvalue    = LDAPString
- * token      = oid from section 4.1 of RFC 2252
- * xtoken     = ("X-" / "x-") token
+ * extype     = oid (from Section 1.4 of RFC4512)
+ * exvalue    = LDAPString (from Section 4.1.2 of RFC4511)
+ * host       = host from Section 3.2.2 of RFC3986
+ * port       = port from Section 3.2.3 of RFC3986
+ * filter     = filter from Section 3 of RFC 4515
+ * </pre>
+ * 
+ * From Section 3.2.1/2 of RFC3986
+ * <pre>
+ * host        = IP-literal / IPv4address / reg-name
+ * port        = *DIGIT
+ * IP-literal  = "[" ( IPv6address / IPvFuture  ) "]"
+ * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+ * IPv6address = 6( h16 ":" ) ls32 
+ *               | "::" 5( h16 ":" ) ls32
+ *               | [               h16 ] "::" 4( h16 ":" ) ls32
+ *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+ *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+ *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+ *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+ *               | [ *5( h16 ":" ) h16 ] "::"              h16
+ *               | [ *6( h16 ":" ) h16 ] "::"
+ * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+ * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+ * reg-name    = *( unreserved / pct-encoded / sub-delims )
+ * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ * pct-encoded = "%" HEXDIG HEXDIG
+ * sub-delims  = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="
+ * h16         = 1*4HEXDIG
+ * ls32        = ( h16 ":" h16 ) / IPv4address
+ * DIGIT       = 0..9
+ * ALPHA       = A-Z / a-z
+ * HEXDIG      = DIGIT / A-F / a-f
  * </pre>
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -110,6 +140,9 @@ public class LdapUrl
 
     /** modal parameter that forces explicit scope rendering in toString */
     private boolean forceScopeRendering;
+    
+    /** The type of host we use */
+    private HostTypeEnum hostType = HostTypeEnum.REGULAR_NAME;
 
     /** A regexp for attributes */
     private static final Pattern ATTRIBUTE = Pattern
@@ -318,16 +351,18 @@ public class LdapUrl
 
     /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;host&gt; ::= &lt;hostname&gt; ':' &lt;hostnumber&gt;<br>
-     * &lt;hostname&gt; ::= *[ &lt;domainlabel&gt; "." ] &lt;toplabel&gt;<br>
-     * &lt;domainlabel&gt; ::= &lt;alphadigit&gt; | &lt;alphadigit&gt;
*[
-     * &lt;alphadigit&gt; | "-" ] &lt;alphadigit&gt;<br>
-     * &lt;toplabel&gt; ::= &lt;alpha&gt; | &lt;alpha&gt; *[ &lt;alphadigit&gt;
|
-     * "-" ] &lt;alphadigit&gt;<br>
-     * &lt;hostnumber&gt; ::= &lt;digits&gt; "." &lt;digits&gt; "."
-     * &lt;digits&gt; "." &lt;digits&gt;
-     * </p>
+     * <pre>
+     * host        = IP-literal / IPv4address / reg-name
+     * port        = *DIGIT
+     * <host> ::= <hostname> ':' <hostnumber><br>
+     * <hostname> ::= *[ <domainlabel> "." ] <toplabel><br>
+     * <domainlabel> ::= <alphadigit> | <alphadigit> *[
+     * <alphadigit> | "-" ] <alphadigit><br>
+     * <toplabel> ::= <alpha> | <alpha> *[ <alphadigit> |
+     * "-" ] <alphadigit><br>
+     * <hostnumber> ::= <digits> "." <digits> "."
+     * <digits> "." <digits>
+     * </pre>
      *
      * @param chars The buffer to parse
      * @param pos The current position in the byte buffer
@@ -338,132 +373,419 @@ public class LdapUrl
     private int parseHost( char[] chars, int pos )
     {
         int start = pos;
-        boolean hadDot = false;
-        boolean hadMinus = false;
-        boolean isHostNumber = true;
-        boolean invalidIp = false;
-        int nbDots = 0;
-        int[] ipElem = new int[4];
 
         // The host will be followed by a '/' or a ':', or by nothing if it's
         // the end.
         // We will search the end of the host part, and we will check some
         // elements.
-        if ( Chars.isCharASCII( chars, pos, '-' ) )
+        switch ( chars[pos] )
         {
-
-            // We can't have a '-' on first position
-            return -1;
+            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' :
+                // 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;
+                }
+                else
+                {
+                    //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 '=' :
+                // A reg-name
+                return parseRegName( chars, pos );
         }
+        
+        host = new String( chars, start, pos - start );
 
-        while ( ( pos < chars.length ) && ( chars[pos] != ':' ) && ( chars[pos]
!= '/' ) )
+        return pos;
+    }
+    
+    
+    /**
+     * parse these rules :
+     * <pre>
+     * IP-literal  = "[" ( IPv6address / IPvFuture  ) "]"
+     * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+     * IPv6address = 6( h16 ":" ) ls32 
+     *               | "::" 5( h16 ":" ) ls32
+     *               | [               h16 ] "::" 4( h16 ":" ) ls32
+     *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+     *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+     *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+     *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+     *               | [ *5( h16 ":" ) h16 ] "::"              h16
+     *               | [ *6( h16 ":" ) h16 ] "::"
+     * h16         = 1*4HEXDIG
+     * ls32        = ( h16 ":" h16 ) / IPv4address
+     */
+    private int parseIpLiteral( char[] chars, int pos )
+    {
+        int start = pos;
+        
+        if ( Chars.isCharASCII( chars, pos, 'v' ) )
         {
-
-            if ( Chars.isCharASCII( chars, pos, '.' ) )
+            // This is an IPvFuture
+            pos++;
+            hostType = HostTypeEnum.IPV_FUTURE;
+            
+            pos = parseIPvFuture( chars, pos );
+            
+            if ( pos != -1 )
             {
-                if ( ( hadMinus ) || ( hadDot ) )
-                {
+                // We don't keep the last char, which is a ']'
+                host = new String( chars, start, pos - start - 1 );
+            }
+            
+            return pos;
+        }
+        else
+        {
+            // An IPV6 host
+            hostType = HostTypeEnum.IPV6;
 
-                    // We already had a '.' just before : this is not allowed.
-                    // Or we had a '-' before a '.' : ths is not allowed either.
-                    return -1;
-                }
+            return parseIPV6( chars, pos );
+        }
+    }
+    
+    
+    /**
+     * Parse the following rules :
+     * <pre>
+     * IPv6address = 6( h16 ":" ) ls32 
+     *               | "::" 5( h16 ":" ) ls32
+     *               | [               h16 ] "::" 4( h16 ":" ) ls32
+     *               | [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
+     *               | [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
+     *               | [ *3( h16 ":" ) h16 ] "::"    h16 ":"   ls32
+     *               | [ *4( h16 ":" ) h16 ] "::"              ls32
+     *               | [ *5( h16 ":" ) h16 ] "::"              h16
+     *               | [ *6( h16 ":" ) h16 ] "::"
+     * h16         = 1*4HEXDIG
+     * ls32        = ( h16 ":" h16 ) / IPv4address
+     * </pre>
+     */
+    private int parseIPV6( char[] chars, int pos )
+    {
+        // Search for the closing ']'
+        int start = pos;
 
-                // Let's check the string we had before the dot.
-                if ( isHostNumber && ( nbDots < 4 ) )
-                {
-                    // We had only digits. It may be an IP adress? Check it
-                    if ( ipElem[nbDots] > 65535 )
-                    {
-                        invalidIp = true;
-                    }
-                }
+        while ( !Chars.isCharASCII( chars, pos, ']' ) )
+        {
+            pos++;
+        }
 
-                hadDot = true;
-                nbDots++;
-                pos++;
-                continue;
+        if ( Chars.isCharASCII( chars, pos, ']' ) )
+        {
+            String hostString = new String( chars, start, pos - start );
+            
+            if ( sun.net.util.IPAddressUtil.isIPv6LiteralAddress( hostString ) )
+            {
+                host = hostString;
+                
+                return  pos + 1;
             }
             else
             {
-                if ( hadDot && Chars.isCharASCII( chars, pos, '-' ) )
-                {
-                    // We can't have a '-' just after a '.'
-                    return -1;
-                }
-
-                hadDot = false;
+                return -1;
             }
+        }
+        
+        return -1;
+    }
+    
 
-            if ( Chars.isDigit( chars, pos ) )
+    /**
+     * Parse these rules :
+     * <pre>
+     * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+     * </pre>
+     * (the "v" has already been parsed)
+     */
+    private int parseIPvFuture( char[] chars, int pos )
+    {
+        // 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 ':' :
+                    pos++;
+                    valueFound = true;
+                    break;
+                    
+                default :
+                    // Wrong char
+                    return -1;
+            }
+        }
+        
+        if ( !valueFound )
+        {
+            return -1;
+        }
+        
+        return pos;
+    }
+    
+    
+    /**
+     * parse these rules :
+     * <pre>
+     * reg-name    = *( unreserved / pct-encoded / sub-delims )
+     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     * pct-encoded = "%" HEXDIG HEXDIG
+     * sub-delims  = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="
+     * HEXDIG      = DIGIT / A-F / a-f
+     * </pre>
+     */
+    private int parseRegName( char[] chars, int pos )
+    {
+        int start = pos;
+        
+        while ( !Chars.isCharASCII( chars, pos, ':' ) && !Chars.isCharASCII( chars,
pos, '/' ) )
+        {
+            switch ( chars[pos] )
             {
-                if ( isHostNumber && ( nbDots < 4 ) )
-                {
-                    ipElem[nbDots] = ( ipElem[nbDots] * 10 ) + ( chars[pos] - '0' );
-
-                    if ( ipElem[nbDots] > 65535 )
+                // 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 '%' : 
+                    if ( Chars.isHex( chars, pos + 1 ) && Chars.isHex( chars, pos
+ 2 ) )
                     {
-                        invalidIp = true;
+                        pos+=3;
                     }
-                }
+                    else
+                    {
+                        return -1;
+                    }
+                    
+                default :
+                    // Wrong char
+                    return -1;
+            }
+        }
+        
+        host = new String( chars, start, pos - start );
+        hostType = HostTypeEnum.REGULAR_NAME;
+        
+        return pos;
+    }
+
+    
+    /**
+     * Parse these rules :
+     * <pre>
+     * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * </pre>
+     * @param chars The buffer to parse
+     * @param pos The current position in the byte buffer
+     * 
+     * @return The new position or -1 if this is not an IPV4 address
+     */
+    private int parseIPV4( char[] chars, int pos )
+    {
+        int[] ipElem = new int[4];
+        int ipPos = pos;
+        int start = pos;
 
-                hadMinus = false;
+        for ( int i = 0; i < 3; i++ )
+        {
+            ipPos = parseDecOctet( chars, ipPos, ipElem, i );
+            
+            if ( ipPos == -1 )
+            {
+                // Not an IPV4 address
+                return -1;
             }
-            else if ( Chars.isAlphaDigitMinus( chars, pos ) )
+            
+            if ( chars[ipPos] != '.' )
             {
-                isHostNumber = false;
-
-                hadMinus = Chars.isCharASCII( chars, pos, '-' );
+                // Not an IPV4 address
+                return -1;
             }
             else
             {
-                return -1;
+                ipPos++;
             }
-
-            pos++;
         }
 
-        if ( start == pos )
+        ipPos = parseDecOctet( chars, ipPos, ipElem, 3 );
+        
+        if ( ipPos == -1 )
+        {
+            // Not an IPV4 address
+            return -1;
+        }
+        else
         {
-            // An empty host is valid
+            pos = ipPos;
+            host = new String( chars, start, pos - start );
+            hostType = HostTypeEnum.IPV4;
+            
             return pos;
         }
-
-        // Checks the hostNumber
-        if ( isHostNumber )
+    }
+    
+    
+    /**
+     * Parse this rule :
+     * <pre>
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * </pre>
+     */
+    private int parseDecOctet( char[] chars, int pos, int[] ipElem, int octetNb )
+    {
+        int ipElemValue = 0;
+        boolean ipElemSeen = false;
+        boolean hasTailingZeroes = false;
+        
+        while ( Chars.isDigit( chars, pos ) )
         {
-            // As this is a host number, we must have 3 dots.
-            if ( nbDots != 3 )
+            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 ( invalidIp )
+            
+            if ( ipElemValue > 255 )
             {
+                // We don't allow IPV4 address with values > 255
                 return -1;
             }
-        }
 
-        // Check if we have a '.' or a '-' in last position
-        if ( hadDot || hadMinus )
+            pos++;
+        }
+        
+        if ( ipElemSeen )
+        {
+            ipElem[octetNb] = ipElemValue;
+            
+            return pos;
+        }
+        else
         {
             return -1;
         }
-
-        host = new String( chars, start, pos - start );
-
-        return pos;
     }
-
+    
 
     /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;port&gt; ::= &lt;digits&gt;<br>
-     * &lt;digits&gt; ::= &lt;digit&gt; &lt;digits-or-null&gt;<br>
-     * &lt;digits-or-null&gt; ::= &lt;digit&gt; &lt;digits-or-null&gt;
| e<br>
-     * &lt;digit&gt; ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
-     * </p>
+     * <pre>
+     * <port> ::= <digit>+<br>
+     * <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
+     * </pre>
      * The port must be between 0 and 65535.
      *
      * @param chars The buffer to parse
@@ -501,9 +823,9 @@ public class LdapUrl
 
     /**
      * Parse this rule : <br>
-     * <p>
-     * &lt;hostport&gt; ::= &lt;host&gt; ':' &lt;port&gt;
-     * </p>
+     * <pre>
+     *   &lt;hostport> ::= &lt;host> [':' &lt;port>]
+     * </pre>
      *
      * @param chars The char array to parse
      * @param pos The current position in the byte buffer
@@ -1274,7 +1596,20 @@ public class LdapUrl
 
         sb.append( scheme );
 
-        sb.append( ( host == null ) ? "" : host );
+        if ( host != null )
+        {
+            switch ( hostType )
+            {
+                case IPV4 :
+                case REGULAR_NAME :
+                    sb.append( host );
+                    break;
+                    
+                case IPV6 :
+                case IPV_FUTURE :
+                    sb.append( '[' ).append( host ).append( ']' );
+            }
+        }
 
         if ( port != -1 )
         {

Modified: directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java?rev=1602776&r1=1602775&r2=1602776&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
(original)
+++ directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/api/ldap/model/url/LdapUrlTest.java
Sun Jun 15 23:00:36 2014
@@ -146,49 +146,50 @@ public class LdapUrlTest
     /**
      * test a LdapUrl with a bad host 2
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost2() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://./" );
+        assertEquals( "ldap://./", new LdapUrl( "ldap://./" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 3
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost3() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a..b/" );
+        assertEquals( "ldap://a..b/", new LdapUrl( "ldap://a..b/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 4
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost4() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://-/" );
+        assertEquals( "ldap://-/", new LdapUrl( "ldap://-/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 5
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost5() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a.b.c-/" );
+        assertEquals( "ldap://a.b.c-/", new LdapUrl( "ldap://a.b.c-/" ).toString() );
     }
 
 
     /**
      * test a LdapUrl with a bad host 6
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost6() throws LdapURLEncodingException
     {
+        assertEquals( "ldap://a.b.-c/", new LdapUrl( "ldap://a.b.-c/" ).toString() );
         new LdapUrl( "ldap://a.b.-c/" );
     }
 
@@ -196,10 +197,10 @@ public class LdapUrlTest
     /**
      * test a LdapUrl with a bad host 7
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHost7() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://a.-.c/" );
+        assertEquals( "ldap://a.-.c/", new LdapUrl( "ldap://a.-.c/" ).toString() );
     }
 
 
@@ -207,7 +208,7 @@ public class LdapUrlTest
      * test a LdapUrl IP host
      */
     @Test
-    public void testDnIPHost() throws LdapURLEncodingException
+    public void testDnIPV4Host() throws LdapURLEncodingException
     {
         assertEquals( "ldap://1.2.3.4/", new LdapUrl( "ldap://1.2.3.4/" ).toString() );
     }
@@ -217,39 +218,42 @@ public class LdapUrlTest
      * test a LdapUrl IP host and port
      */
     @Test
-    public void testDnIPHostPort() throws LdapURLEncodingException
+    public void testDnIPV4HostPort() throws LdapURLEncodingException
     {
         assertEquals( "ldap://1.2.3.4:80/", new LdapUrl( "ldap://1.2.3.4:80/" ).toString()
);
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 1
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will
not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP1() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1/" );
+        assertEquals( "ldap://1.1.1/", new LdapUrl( "ldap://1.1.1/" ).toString() );
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 2
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will
not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP2() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1./" );
+        assertEquals( "ldap://1.1.1./", new LdapUrl( "ldap://1.1.1./" ).toString() );
     }
 
 
     /**
-     * test a LdapUrl with a bad IP host 3
+     * test a LdapUrl with a bad IP host 1 : we should not get an error, but the host will
not be considered 
+     * as an IPV4 address
      */
-    @Test(expected = LdapURLEncodingException.class)
+    @Test
     public void testDnBadHostIP3() throws LdapURLEncodingException
     {
-        new LdapUrl( "ldap://1.1.1.100000/" );
+        assertEquals( "ldap://1.1.1.100000/", new LdapUrl( "ldap://1.1.1.100000/" ).toString()
);
     }
 
 
@@ -274,6 +278,43 @@ public class LdapUrlTest
 
 
     /**
+     * test a LdapUrl IPv6 host
+     */
+    @Test
+    public void testDnIPv6Host() throws LdapURLEncodingException
+    {
+        assertEquals( "ldap://[::]/", new LdapUrl( "ldap://[::]/" ).toString() );
+        assertEquals( "ldap://[1::2]/", new LdapUrl( "ldap://[1::2]/" ).toString() );
+        assertEquals( "ldap://[abcd:EF01:0234:5678:abcd:EF01:0234:5678]/", new LdapUrl( "ldap://[abcd:EF01:0234:5678:abcd:EF01:0234:5678]/"
).toString() );
+        assertEquals( "ldap://[::2]/", new LdapUrl( "ldap://[::2]/" ).toString() );
+        assertEquals( "ldap://[1:2::3:4]/", new LdapUrl( "ldap://[1:2::3:4]/" ).toString()
);
+        assertEquals( "ldap://[1:2:3:4:5:6::]/", new LdapUrl( "ldap://[1:2:3:4:5:6::]/" ).toString()
);
+    }
+
+
+    /**
+     * test a bad LdapUrl IPv6 host
+     * @throws LdapURLEncodingException 
+     */
+    @Test( expected=LdapURLEncodingException.class )
+    public void testDnIPv6BadHost() throws LdapURLEncodingException
+    {
+        new LdapUrl( "ldap://[:]/" );
+    }
+
+
+    /**
+     * test a bad LdapUrl IPv6 host
+     * @throws LdapURLEncodingException 
+     */
+    @Test( expected=LdapURLEncodingException.class )
+    public void testDnIPv6BadHost2() throws LdapURLEncodingException
+    {
+        new LdapUrl( "ldap://[1::2::3]/" );
+    }
+
+
+    /**
      * test a LdapUrl with valid simpleDN
      */
     @Test



Mime
View raw message