Return-Path: X-Original-To: apmail-directory-commits-archive@www.apache.org Delivered-To: apmail-directory-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B2ABA11576 for ; Sun, 15 Jun 2014 23:01:04 +0000 (UTC) Received: (qmail 80077 invoked by uid 500); 15 Jun 2014 23:01:04 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 80041 invoked by uid 500); 15 Jun 2014 23:01:04 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 80032 invoked by uid 99); 15 Jun 2014 23:01:04 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 15 Jun 2014 23:01:04 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 15 Jun 2014 23:01:02 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 03A3B2388AA9; Sun, 15 Jun 2014 23:00:37 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: commits@directory.apache.org From: elecharny@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20140615230037.03A3B2388AA9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 : + *
    + *
  • IPV4 : IPV4 host
  • + *
  • IPV6 : IPV6 host
  • + *
  • IPV_FUTURE : IP v Future host
  • + *
  • REGULAR_NAME : A regular name
  • + *
  • + *
+ * + * @author Apache Directory Project + */ +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 : *
- * 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
+ * 
+ * + * From Section 3.2.1/2 of RFC3986 + *
+ * 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
  * 
* @author Apache Directory Project */ @@ -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 :
- *

- * <host> ::= <hostname> ':' <hostnumber>
- * <hostname> ::= *[ <domainlabel> "." ] <toplabel>
- * <domainlabel> ::= <alphadigit> | <alphadigit> *[ - * <alphadigit> | "-" ] <alphadigit>
- * <toplabel> ::= <alpha> | <alpha> *[ <alphadigit> | - * "-" ] <alphadigit>
- * <hostnumber> ::= <digits> "." <digits> "." - * <digits> "." <digits> - *

+ *
+     * host        = IP-literal / IPv4address / reg-name
+     * port        = *DIGIT
+     *  ::=  ':' 
+ * ::= *[ "." ]
+ * ::= | *[ + * | "-" ]
+ * ::= | *[ | + * "-" ]
+ * ::= "." "." + * "." + *
* * @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 : + *
+     * 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 :
+     * 
+     * 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 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 : + *
+     * IPvFuture   = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
+     * 
+ * (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 : + *
+     * reg-name    = *( unreserved / pct-encoded / sub-delims )
+     * unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"
+     * pct-encoded = "%" HEXDIG HEXDIG
+     * sub-delims  = "!" | "$" | "&" | "'" | "(" | ")" | "*" | "+" | "," | ";" | "="
+     * HEXDIG      = DIGIT / A-F / a-f
+     * 
+ */ + 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 : + *
+     * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * 
+ * @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 : + *
+     * dec-octet   = DIGIT | [1-9] DIGIT | "1" 2DIGIT | "2" [0-4] DIGIT | "25" [0-5]
+     * 
+ */ + 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 :
- *

- * <port> ::= <digits>
- * <digits> ::= <digit> <digits-or-null>
- * <digits-or-null> ::= <digit> <digits-or-null> | e
- * <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 - *

+ *
+     *  ::= +
+ * ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 + *
* The port must be between 0 and 65535. * * @param chars The buffer to parse @@ -501,9 +823,9 @@ public class LdapUrl /** * Parse this rule :
- *

- * <hostport> ::= <host> ':' <port> - *

+ *
+     *   <hostport> ::= <host> [':' <port>]
+     * 
* * @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