From 26b52046f808b8dde21b8842d2a8834e9dbc4527 Mon Sep 17 00:00:00 2001 From: "miodrag%netscape.com" Date: Mon, 18 Dec 2000 14:02:20 +0000 Subject: [PATCH] Updtates for LDAPJDK 4.13 --- .../ldapjdk/netscape/ldap/LDAPAttribute.java | 14 +- .../ldapjdk/netscape/ldap/LDAPConnection.java | 75 ++++- .../netscape/ldap/LDAPReferralException.java | 16 + .../netscape/ldap/LDAPSearchResults.java | 18 +- .../ldapjdk/netscape/ldap/LDAPUrl.java | 316 ++++++++++++------ .../netscape/ldap/client/JDAPFilter.java | 13 +- .../netscape/ldap/client/JDAPFilterOpers.java | 50 ++- .../ldap/client/opers/JDAPSearchRequest.java | 3 +- .../ldap/controls/LDAPSortControl.java | 2 +- .../netscape/ldap/errors/ErrorCodes.props | 8 +- .../netscape/ldap/errors/ErrorCodes_de.props | 8 +- .../netscape/ldap/errors/ErrorCodes_fr.props | 8 +- .../ldap/factory/JSSESocketFactory.java | 4 +- .../netscape/ldap/util/ConnectionPool.java | 38 ++- .../netscape/ldap/util/DSMLWriter.java | 4 +- 15 files changed, 435 insertions(+), 142 deletions(-) diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPAttribute.java b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPAttribute.java index 10ed2dee42c6..85cb68bc97f1 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPAttribute.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPAttribute.java @@ -510,11 +510,21 @@ public class LDAPAttribute implements java.io.Serializable { } byte[] val = (byte[])values[i]; try { - sb.append(new String(val, "UTF8")); + String sval = new String(val, "UTF8"); + if (sval.length() == 0 && val.length > 0) { + sb.append(""); + } + else { + sb.append(sval); + } + } catch (Exception e) { if (val != null) { + sb.append(""); } else { sb.append("null value"); diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java index 2f9fef140fdd..1b6be8b43602 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPConnection.java @@ -260,11 +260,11 @@ public class LDAPConnection /** * Properties */ - private final static Float SdkVersion = new Float(4.12f); + private final static Float SdkVersion = new Float(4.13f); private final static Float ProtocolVersion = new Float(3.0f); private final static String SecurityVersion = new String("none,simple,sasl"); private final static Float MajorVersion = new Float(4.0f); - private final static Float MinorVersion = new Float(0.12f); + private final static Float MinorVersion = new Float(0.13f); private final static String DELIM = "#"; private final static String PersistSearchPackageName = "netscape.ldap.controls.LDAPPersistSearchControl"; @@ -2107,7 +2107,14 @@ public class LDAPConnection if (results == null) { return null; } - return results.next (); + LDAPEntry entry = results.next(); + + // cleanup required for referral connections + while (results.hasMoreElements()) { + ; // do nothing + } + + return entry; } /** @@ -2180,6 +2187,15 @@ public class LDAPConnection LDAPEntry returnValue; LDAPConnection connection = new LDAPConnection (); + if (toGet.isSecure()) { + LDAPSocketFactory factory = toGet.getSocketFactory(); + if (factory == null) { + throw new LDAPException("No socket factory for LDAPUrl", + LDAPException.OTHER); + } + System.err.println(factory); + connection.setSocketFactory(factory); + } connection.connect (host, port); returnValue = connection.read (DN, attributes); @@ -2318,6 +2334,14 @@ public class LDAPConnection int scope = toGet.getScope (); LDAPConnection connection = new LDAPConnection (); + if (toGet.isSecure()) { + LDAPSocketFactory factory = toGet.getSocketFactory(); + if (factory == null) { + throw new LDAPException("No socket factory for LDAPUrl", + LDAPException.OTHER); + } + connection.setSocketFactory(factory); + } connection.connect (host, port); LDAPSearchResults results; @@ -5321,7 +5345,7 @@ public class LDAPConnection /** * Reports if the class is running in a Netscape browser. - * @return true if the class is running in a Netscape browser. + * @return true if the class is running in a Netscape browser. */ public static boolean isNetscape() { return isCommunicator; @@ -5333,6 +5357,49 @@ public class LDAPConnection } } + /** + * Returns the string representation for this LDAPConnection. + *

+ * For example: + * + *

LDAPConnection {ldap://dilly:389 (2) ldapVersion:3 bindDN:"uid=admin,o=iplanet.com"}
+ * + * For cloned connections, the number of LDAPConnection instances sharing the + * same physical connection is shown in parenthesis following the ldap url. + * If a LDAPConnection is not cloned, this number is omitted from the string + * representation. + * + * @return string representation of the connection. + * @see netscape.ldap.LDAPConnection#clone + */ + public String toString() { + int cloneCnt = (m_thread == null) ? 0 : m_thread.getClientCount(); + StringBuffer sb = new StringBuffer("LDAPConnection {"); + //url + sb.append((m_factory == null ? "ldap" : "ldaps")); + sb.append("://"); + sb.append(getHost()); + sb.append(":"); + sb.append(getPort()); + // clone count + if (cloneCnt > 1) { + sb.append(" ("); + sb.append(cloneCnt); + sb.append(")"); + } + // ldap version + sb.append(" ldapVersion:"); + sb.append(m_protocolVersion); + // bind DN + sb.append(" bindDN:\""); + if (getAuthenticationDN() != null) { + sb.append(getAuthenticationDN()); + } + sb.append("\"}"); + + return sb.toString(); + } + /** * Prints out the LDAP Java SDK version and the highest LDAP * protocol version supported by the SDK. To view this diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPReferralException.java b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPReferralException.java index 2e84ee383e13..cdf515297939 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPReferralException.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPReferralException.java @@ -149,4 +149,20 @@ public class LDAPReferralException extends LDAPException { } return res; } + + /** + * Gets the string representation of the referral exception, + * which includes the result code, the message sent back + * from the LDAP server and the list of referrals. + * + * @return string representation of exception. + * @see netscape.ldap.LDAPException#errorCodeToString(int) + */ + public String toString() { + String str = super.toString(); + for (int i=0; i < m_referrals.length; i++) { + str += "\n" + m_referrals[i]; + } + return str; + } } diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSearchResults.java b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSearchResults.java index b1cab67da983..9ff3e3521082 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSearchResults.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPSearchResults.java @@ -286,7 +286,12 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable { while (referralResults.size() > 0) { Object obj = null; if ((obj=nextReferralElement()) != null) { - entries.addElement(obj); + if (obj instanceof LDAPException) { + add((LDAPException)obj); // put it back + } + else { + entries.addElement(obj); + } } } } @@ -476,18 +481,19 @@ public class LDAPSearchResults implements Enumeration, java.io.Serializable { * @return count of search results immediatly available for processing */ public int getCount() { - int count = entries.size(); + while (resultSource != null && resultSource.getMessageCount() > 0) { + fetchResult(); + } + + int count = entries.size(); + for ( int i = 0; i < referralResults.size(); i++ ) { LDAPSearchResults res = (LDAPSearchResults)referralResults.elementAt(i); count += res.getCount(); } - if ( resultSource != null ) { - count += resultSource.getMessageCount(); - } - if ( exceptions != null ) { count += exceptions.size(); } diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java index d81431ab02c3..cc14792f1327 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/LDAPUrl.java @@ -24,14 +24,16 @@ package netscape.ldap; import java.util.*; import java.io.*; import java.net.MalformedURLException; +import netscape.ldap.factory.*; /** * Represents an LDAP URL. The complete specification for LDAP URLs is in * RFC 1959. LDAP URLs have the following format: + * TARGET="_blank">RFC 1959. In addition, the secure ldap (ldaps://) is also + * supported. LDAP URLs have the following format: * *
- * "ldap://" [ hostName [":" portNumber] ] "/"
+ * "ldap[s]://" [ hostName [":" portNumber] ] "/"
  *                      distinguishedName
  *          ["?" attributeList ["?" scope
  *                      "?" filterString ] ]
@@ -82,13 +84,22 @@ public class LDAPUrl implements java.io.Serializable {
     static final long serialVersionUID = -3245440798565713640L;
     public static String defaultFilter = "(objectClass=*)";
 
-    private String hostName;
-    private int portNumber;
-    private String DN;
-    private Vector attributes;
-    private int scope;
-    private String filter;
-    private String URL;
+    private String m_hostName;
+    private int m_portNumber;
+    private String m_DN;
+    private Vector m_attributes;
+    private int m_scope;
+    private String m_filter;
+    private String m_URL;
+    private boolean m_secure;
+    
+    private static LDAPSocketFactory m_factory;
+
+    /**
+     * The default port number for secure LDAP connections.
+     * @see netscape.ldap.LDAPUrl#LDAPUrl(java.lang.String, int, java.lang.String, java.lang.String[], int, java.lang.String, boolean)
+     */    
+    public static final int DEFAULT_SECURE_PORT = 636;
 
     /**
      * Constructs a URL object with the specified string as URL.
@@ -96,65 +107,90 @@ public class LDAPUrl implements java.io.Serializable {
      * @exception MalformedURLException failed to parse URL
      */
     public LDAPUrl (String url) throws java.net.MalformedURLException {
-        attributes = null;
-        scope = LDAPv2.SCOPE_BASE;
-        filter = defaultFilter;
-        URL = url;
+        m_attributes = null;
+        m_scope = LDAPv2.SCOPE_BASE;
+        m_filter = defaultFilter;
+        m_URL = url;
 
         parseUrl(url);
     }
 
     /**
-     * Parse URL as defined in RFC 1959
+     * Parse URL as defined in RFC 1959. Beyond the RFC, the secure ldap
+     * (ldaps) is also supported.
      */
     private void parseUrl(String url) throws MalformedURLException {
         StringTokenizer urlParser = new StringTokenizer (url, ":/?", true);
         String currentToken;
         String str = null;
 
-        currentToken = urlParser.nextToken();
-        if (!currentToken.equalsIgnoreCase ("LDAP"))
-            throw new MalformedURLException ();
+        try {
+            currentToken = urlParser.nextToken();
+            if (currentToken.equalsIgnoreCase ("LDAPS")) {
+                m_secure = true;
+            }
+            else if (!currentToken.equalsIgnoreCase ("LDAP")) {
+                throw new MalformedURLException ();
+            }
 
-        currentToken = urlParser.nextToken();
-        if (!currentToken.equals(":")) {
+            currentToken = urlParser.nextToken();
+            if (!currentToken.equals(":")) {
+                throw new MalformedURLException ();
+            }
+            currentToken = urlParser.nextToken();
+            if (!currentToken.equals("/")) {
+                throw new MalformedURLException ();
+            }
+            currentToken = urlParser.nextToken();
+            if (!currentToken.equals("/")) {
+                throw new MalformedURLException ();
+            }
+        
+            currentToken = urlParser.nextToken();
+        }
+        catch (NoSuchElementException e) {
             throw new MalformedURLException ();
         }
-        currentToken = urlParser.nextToken();
-        if (!currentToken.equals("/")) {
-            throw new MalformedURLException ();
-        }
-        currentToken = urlParser.nextToken();
-        if (!currentToken.equals("/")) {
-            throw new MalformedURLException ();
-        }
-
-        currentToken = urlParser.nextToken();
-
+            
+        // host-port
         if (currentToken.equals ("/")) {
-            hostName = null;
-            portNumber = LDAPv2.DEFAULT_PORT;
+            m_hostName = null;
+            m_portNumber = m_secure ? DEFAULT_SECURE_PORT : LDAPv2.DEFAULT_PORT;
+        } else if (currentToken.equals (":")) {
+                // port number without host name is not allowed
+               throw new MalformedURLException ("No hostname");
+        } else if (currentToken.equals ("?")) {
+            throw new MalformedURLException ("No host[:port]");
         } else {
-            hostName = currentToken;
+            m_hostName = currentToken;
             if (urlParser.countTokens() == 0) {
-                portNumber = LDAPv2.DEFAULT_PORT;
+                m_portNumber = m_secure ? DEFAULT_SECURE_PORT : LDAPv2.DEFAULT_PORT;
                 return;
             }
             currentToken = urlParser.nextToken (); // either ":" or "/"
 
             if (currentToken.equals (":")) {
                 try {
-                    portNumber = Integer.parseInt (urlParser.nextToken());
+                    m_portNumber = Integer.parseInt (urlParser.nextToken());
                 } catch (NumberFormatException nf) {
-                    throw new MalformedURLException ();
+                    throw new MalformedURLException ("Port not a number");
+                } catch (NoSuchElementException ex) {
+                    throw new MalformedURLException ("No port number");
                 }
                     
                 if (urlParser.countTokens() == 0) {
                     return;
                 }
-                urlParser.nextToken ();   // "/"
-            } else
-                portNumber = LDAPv2.DEFAULT_PORT;
+                else if (! urlParser.nextToken().equals("/")) {
+                   throw new MalformedURLException ();
+                }
+
+            } else if (currentToken.equals ("/")) {
+                m_portNumber = m_secure ? DEFAULT_SECURE_PORT : LDAPv2.DEFAULT_PORT;
+            } else {
+                // expecting ":" or "/"
+                throw new MalformedURLException ();
+            }
         }
 
 
@@ -162,11 +198,11 @@ public class LDAPUrl implements java.io.Serializable {
         if (!urlParser.hasMoreTokens ()) {
             return;
         }
-        DN = decode(readNextConstruct(urlParser));
-        if (DN.equals("?")) {
-            DN = "";
+        m_DN = decode(readNextConstruct(urlParser));
+        if (m_DN.equals("?")) {
+            m_DN = "";
         }
-        else if (DN.equals("/")) {
+        else if (m_DN.equals("/")) {
             throw new MalformedURLException ();
         }            
             
@@ -178,10 +214,10 @@ public class LDAPUrl implements java.io.Serializable {
         if (!str.equals("?")) {
             StringTokenizer attributeParser = new
                 StringTokenizer (decode(str), ", ");
-            attributes = new Vector ();
+            m_attributes = new Vector ();
 
             while (attributeParser.hasMoreTokens()) {
-                attributes.addElement (attributeParser.nextToken());
+                m_attributes.addElement (attributeParser.nextToken());
             }
         }
 
@@ -191,8 +227,8 @@ public class LDAPUrl implements java.io.Serializable {
         }
         str = readNextConstruct(urlParser);
         if (!str.equals("?")) {
-            scope = getScope(str);
-            if (scope < 0) {
+            m_scope = getScope(str);
+            if (m_scope < 0) {
                 throw new MalformedURLException("Bad scope:" + str);
             }
         }
@@ -202,10 +238,10 @@ public class LDAPUrl implements java.io.Serializable {
             return;
         }
         str = readNextConstruct(urlParser);
-        filter = decode(str);
-        checkBalancedParentheses(filter);
-        if (!filter.startsWith("(") && !filter.endsWith(")")) {
-            filter = "(" + filter + ")";
+        m_filter = decode(str);
+        checkBalancedParentheses(m_filter);
+        if (!m_filter.startsWith("(") && !m_filter.endsWith(")")) {
+            m_filter = "(" + m_filter + ")";
         }
 
         // Nothing after the filter is allowed
@@ -243,21 +279,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @param DN distinguished name of the object
      */
     public LDAPUrl (String host, int port, String DN) {
-        if (host != null) {
-            if (port != LDAPv2.DEFAULT_PORT)
-                URL = "LDAP://" + host + ":" + String.valueOf (port) +
-                  "/" + encode (DN);
-            else
-                URL = "LDAP://" + host + "/" + encode (DN);
-        } else
-            URL = "LDAP:///" + encode (DN);
-
-        this.hostName = host;
-        this.DN = DN;
-        portNumber = port;
-        filter = defaultFilter;
-        attributes = null;
-        scope = LDAPv2.SCOPE_BASE;
+        initialize(host, port, DN, null, LDAPv2.SCOPE_BASE, defaultFilter, false);
     }
 
     /**
@@ -276,15 +298,7 @@ public class LDAPUrl implements java.io.Serializable {
     public LDAPUrl (String host, int port, String DN,
         String attributes[], int scope, String filter) {
 
-        if (attributes != null) {
-            Vector list = new Vector();
-            for (int k = 0; k < attributes.length; k++) {
-                list.addElement(attributes[k]);
-            }
-            initialize(host, port, DN, list.elements(), scope, filter);
-        } else {
-            initialize(host, port, DN, null, scope, filter);
-        }
+        this(host, port, DN, attributes, scope, filter, false);
     }
 
     /**
@@ -303,37 +317,66 @@ public class LDAPUrl implements java.io.Serializable {
     public LDAPUrl (String host, int port, String DN,
       Enumeration attributes, int scope, String filter) {
 
-        initialize(host, port, DN, attributes, scope, filter);
+        initialize(host, port, DN, attributes, scope, filter, false);
     }
 
+    /**
+     * Constructs a full-blown LDAP URL to specify an LDAP search operation.
+     * @param host host name of the LDAP server, or null for "nearest X.500/LDAP"
+     * @param port port number of the LDAP server (use LDAPv2.DEFAULT_PORT for
+     * the default non-secure port or LDAPUrl.DEFAULT_SECURE_PORT for the default
+     * secure port)
+     * @param DN distinguished name of the object
+     * @param attributes list of the attributes to return. Use null for "all
+     * attributes."
+     * @param scope depth of the search (in DN namespace). Use one of the LDAPv2 scopes: 
+     * SCOPE_BASE, SCOPE_ONE, or SCOPE_SUB.
+     * @param filter LDAP filter string (as defined in RFC 1558). Use null for
+     * no filter (this effectively makes the URL reference a single object).
+     * @param secure flag if secure ldap protocol (ldaps) is to be used.
+     */
+    public LDAPUrl (String host, int port, String DN,
+      String[] attributes, int scope, String filter, boolean secure) {
+
+        if (attributes != null) {
+            Vector list = new Vector();
+            for (int k = 0; k < attributes.length; k++) {
+                list.addElement(attributes[k]);
+            }
+            initialize(host, port, DN, list.elements(), scope, filter, secure);
+        } else {
+            initialize(host, port, DN, null, scope, filter, secure);
+        }
+    }
+
+
     /**
      * Initializes URL object.
      */
     private void initialize (String host, int port, String DN,
-      Enumeration attributes, int scope, String filter) {
+      Enumeration attributes, int scope, String filter, boolean secure) {
 
-        this.hostName = host;
-        this.DN = DN;
-        portNumber = port;
-        this.filter = (filter != null) ? filter : defaultFilter;
-        this.scope = scope;
+        m_hostName = host;
+        m_DN = DN;
+        m_portNumber = port;
+        m_filter = (filter != null) ? filter : defaultFilter;
+        m_scope = scope;
+        m_secure = secure;
 
         if (attributes != null) {
-            this.attributes = new Vector ();
+            m_attributes = new Vector ();
             while (attributes.hasMoreElements()) {
-                this.attributes.addElement (attributes.nextElement());
+                m_attributes.addElement (attributes.nextElement());
             }
         } else
-            this.attributes = null;
+            m_attributes = null;
 
-        StringBuffer url = new StringBuffer ("LDAP://");
+        StringBuffer url = new StringBuffer (secure ? "LDAPS://" :"LDAP://");
 
         if (host != null) {
             url.append (host);
-            if (port != LDAPv2.DEFAULT_PORT) {
-                url.append (':');
-                url.append (String.valueOf (port));
-            }
+            url.append (':');
+            url.append (String.valueOf (port));
         }
 
         url.append ('/');
@@ -341,7 +384,7 @@ public class LDAPUrl implements java.io.Serializable {
 
         if (attributes != null) {
             url.append ('?');
-            Enumeration attrList = this.attributes.elements();
+            Enumeration attrList = m_attributes.elements();
             boolean firstElement = true;
 
             while (attrList.hasMoreElements()) {
@@ -374,7 +417,7 @@ public class LDAPUrl implements java.io.Serializable {
             url.append (filter);
         }
 
-        URL = url.toString();
+        m_URL = url.toString();
     }
 
     /**
@@ -382,7 +425,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @return LDAP host.
      */
     public String getHost () {
-        return hostName;
+        return m_hostName;
     }
 
     /**
@@ -390,7 +433,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @return port number.
      */
     public int getPort () {
-        return portNumber;
+        return m_portNumber;
     }
 
     /**
@@ -398,7 +441,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @return target distinguished name.
      */
     public String getDN () {
-        return DN;
+        return m_DN;
     }
 
     /**
@@ -407,10 +450,10 @@ public class LDAPUrl implements java.io.Serializable {
      * @return enumeration of attributes.
      */
     public Enumeration getAttributes () {
-        if (attributes == null)
+        if (m_attributes == null)
             return null;
         else
-            return attributes.elements();
+            return m_attributes.elements();
     }
 
     /**
@@ -419,10 +462,10 @@ public class LDAPUrl implements java.io.Serializable {
      * @return string array of attributes.
      */
     public String[] getAttributeArray () {
-        if (attributes == null)
+        if (m_attributes == null)
             return null;
         else {
-            String[] attrNames = new String[attributes.size()];
+            String[] attrNames = new String[m_attributes.size()];
             Enumeration attrs = getAttributes();
             int i = 0;
 
@@ -440,7 +483,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @return search scope.
      */
     public int getScope () {
-        return scope;
+        return m_scope;
     }
 
     /**
@@ -469,7 +512,7 @@ public class LDAPUrl implements java.io.Serializable {
      * @return the search filter.
      */
     public String getFilter () {
-        return filter;
+        return m_filter;
     }
 
     /**
@@ -477,9 +520,66 @@ public class LDAPUrl implements java.io.Serializable {
      * @return the LDAP search expression in URL form.
      */
     public String getUrl () {
-        return URL;
+        return m_URL;
     }
 
+    /**
+     * Returns true if the secure ldap protocol is used.
+     * @return true if ldaps is used.
+     */
+    public boolean isSecure() {
+        return m_secure;
+    }
+
+    /**
+     * Gets the socket factory to be used for ldaps:// URLs.
+     * 

+ * If the factory is not explicitly specified with + * LDAPUrl.setSocketFactory, the method will + * attempt the determine the default factory based on the + * available factories in the netscape.ldap.factory package. + * + * @return the socket factory to be used for ldaps:// URLs + */ + public static LDAPSocketFactory getSocketFactory() { + + if (m_factory == null) { + + // No factory explicity set, try to determine + // the default one. + try { + // First try iPlanet JSSSocketFactory + m_factory = new JSSSocketFactory(); + } + catch (Throwable e) { + } + + if (m_factory != null) { + return m_factory; + } + + try { + // then try Sun JSSESocketFactory + m_factory = new JSSESocketFactory(null); + } + catch (Throwable e) { + } + } + + return m_factory; + } + + /** + * Sets the socket factory to be used for ldaps:// URLs. + * Overrides the default factory assigned by the LDAPUrl + * class. + * @param the socket factory to be used for ldaps:// URLs + * @see netscape.ldap.LDAPUrl#getSocketFactory + */ + public static void setSocketFactory(LDAPSocketFactory factory) { + m_factory = factory; + } + /** * Reads next construct from the given string parser. * @param parser the string parser @@ -649,16 +749,16 @@ public class LDAPUrl implements java.io.Serializable { return false; } - if ( attributes == null ) { - if ( url.attributes != null ) { + if ( m_attributes == null ) { + if ( url.m_attributes != null ) { return false; } - } else if ( attributes.size() != url.attributes.size() ) { + } else if ( m_attributes.size() != url.m_attributes.size() ) { return false; } else { - for( int i = 0; i < attributes.size(); i++ ) { - if ( attributes.elementAt( i ) != - url.attributes.elementAt( i ) ) { + for( int i = 0; i < m_attributes.size(); i++ ) { + if ( m_attributes.elementAt( i ) != + url.m_attributes.elementAt( i ) ) { return false; } } diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilter.java b/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilter.java index 15d739b46eb4..7e4fc3d1b27e 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilter.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilter.java @@ -80,8 +80,12 @@ public abstract class JDAPFilter { public static JDAPFilter getFilter(String filter) { String f = new String(filter); f.trim(); - if (f.startsWith("(") && f.endsWith(")")) { - return getFilterComp(f.substring(1,f.length()-1)); + if (f.startsWith("(") || f.endsWith(")")) { + if (f.startsWith("(") && f.endsWith(")")) { + return getFilterComp(f.substring(1,f.length()-1)); + } + //unbalanced parentheses + throw new IllegalArgumentException("Bad search filter"); } return getFilterComp(filter); } @@ -178,6 +182,11 @@ public abstract class JDAPFilter { String type = item.substring(0, idx).trim(); String value = item.substring(idx+1).trim(); /* skip = */ + // Only values can contain escape sequences + if (type.indexOf('\\') >= 0) { + throw new IllegalArgumentException("Bad search filter"); + } + /* make decision by looking at the type */ type.trim(); if (type.endsWith("~")) { diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilterOpers.java b/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilterOpers.java index d6ec7d6ba1bb..5f25ba052874 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilterOpers.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/client/JDAPFilterOpers.java @@ -31,7 +31,7 @@ import netscape.ldap.ber.stream.*; * returns the ber octet string for the specified string with escape * characters. */ -class JDAPFilterOpers { +public class JDAPFilterOpers { private static final String escapeKey = "\\"; private static final boolean m_debug = false; @@ -49,6 +49,54 @@ class JDAPFilterOpers { return new BEROctetString(str); } + /** + * Preprocess the LDAPv2 RFC1960 style filter escape sequences (precede + * a character with a a backslash) and convert them into the + * LDAPv3 style RFC2254 escape sequences (encode a character as a backslash + * followed by the two hex digits representing the character ASCII value). + * + * LDAPv3 style unescaping is done from the getByteValues()method. We must + * process LDAPv2 escaped characters earlier to get rid of possible "\(" \)" + * sequences which would make filter parsing in the JDAPFilter operate incorrectly. + */ + public static String convertLDAPv2Escape(String filter) { + + if (filter.indexOf('\\') < 0) { + return filter; + } + + StringBuffer sb = new StringBuffer(); + int i=0, start=0, len=filter.length(); + while(start < len && (i = filter.indexOf('\\', start)) >= 0 ) { + sb.append(filter.substring(start, i+1)); // include also '\' + try { + char c = filter.charAt(i+1); + + if ((c >= ' ' && c < 127) && !isHexDigit(c)) { + sb.append(Integer.toHexString(c)); + } + else { + sb.append(c); + } + + start = i + 2; + } + catch (IndexOutOfBoundsException e) { + throw new IllegalArgumentException("Bad search filter"); + } + } + + if (start < len) { + sb.append(filter.substring(start)); + } + + return sb.toString(); + } + + private static boolean isHexDigit(char c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + } + /** * This method converts the given string into bytes. It also handles * the escape characters embedded in the given string. diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/client/opers/JDAPSearchRequest.java b/directory/java-sdk/ldapjdk/netscape/ldap/client/opers/JDAPSearchRequest.java index 0bca75b91bc7..b52f0b1aad6c 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/client/opers/JDAPSearchRequest.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/client/opers/JDAPSearchRequest.java @@ -107,7 +107,8 @@ public class JDAPSearchRequest extends JDAPBaseDNRequest m_time_limit = time_limit; m_attrs_only = attrs_only; m_filter = (filter == null) ? DEFAULT_FILTER : filter; - m_parsedFilter = JDAPFilter.getFilter(m_filter); + m_parsedFilter = JDAPFilter.getFilter( + JDAPFilterOpers.convertLDAPv2Escape(m_filter)); if (m_parsedFilter == null){ throw new IllegalArgumentException("Bad search filter"); } diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/controls/LDAPSortControl.java b/directory/java-sdk/ldapjdk/netscape/ldap/controls/LDAPSortControl.java index 88685b601a0f..902f4d5d2491 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/controls/LDAPSortControl.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/controls/LDAPSortControl.java @@ -265,7 +265,7 @@ public class LDAPSortControl extends LDAPControl { BERSequence seq = (BERSequence)BERElement.getElement(decoder, inStream, nRead ); /* First is result code */ - int m_resultCode = ((BEREnumerated)seq.elementAt( 0 )).getValue(); + m_resultCode = ((BEREnumerated)seq.elementAt( 0 )).getValue(); /* Then, possibly an attribute that failed sorting */ if(seq.size() == 1) { return; diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes.props b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes.props index 0fb3ddefaaed..ad480130a473 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes.props +++ b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes.props @@ -27,9 +27,9 @@ 48=Inappropriate authentication 49=Invalid credentials 50=Insufficient access -51=DSA is busy -52=DSA is unavailable -53=DSA is unwilling to perform +51=LDAP server is busy +52=LDAP server is unavailable +53=LDAP server is unwilling to perform 54=Loop detected 64=Naming violation 65=Object class violation @@ -37,7 +37,7 @@ 67=Operation not allowed on RDN 68=Already exists 69=Cannot modify object class -71=Affects multiple DSAs +71=Affects multiple LDAP servers 80=Unknown error 81=Cannot contact LDAP server 85=Client Timelimit exceeded diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_de.props b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_de.props index c87241154cba..fed73a874d45 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_de.props +++ b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_de.props @@ -27,9 +27,9 @@ 48=Unpassende Echtheitsprüfung 49=Ungültige Echtheitsnachweise 50=Ungenügender Zugriff -51=DSA ist belegt -52=DSA ist nicht verfügbar -53=DSA ist nicht zur Durchführung bereit +51=LDAP-Server ist belegt +52=LDAP-Server ist nicht verfügbar +53=LDAP-Server ist nicht zur Durchführung bereit 54=Schleife festgestellt 64=Verstoß gegen Benennungsregeln 65=Verstoß gegen Objektklasse @@ -37,7 +37,7 @@ 67=Operation nicht für RDN zulässig 68=Bereits vorhanden 69=Objektklasse kann nicht geändert werden -71=Wirkt sich auf mehrere DSAs aus +71=Wirkt sich auf mehrere LDAP-Servers aus 80=Unbekannter Fehler 81=Verbindung zu LDAP-Server nicht möglich 85=Client-Zeitbeschränkung überschritten diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_fr.props b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_fr.props index ca4dd26139f6..24573d6b7f4b 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_fr.props +++ b/directory/java-sdk/ldapjdk/netscape/ldap/errors/ErrorCodes_fr.props @@ -27,9 +27,9 @@ 48=Authentification inadéquate 49=Références non valides 50=Accès insuffisant -51=DSA est occupé -52=DSA n'est pas disponible -53=DSA ne veut pas trater la demande +51=Le serveur LDAP est occupé +52=Le serveur LDAP n'est pas disponible +53=Le serveur LDAP ne veut pas traiter la demande 54=Boucle détectée 64=Violation d'attribution de nom 65=Violation de classe d'objet @@ -37,7 +37,7 @@ 67=Opération non autorisée sur RDN 68=Existe déjà 69=Impossible de modifier la classe d'objet -71=Concerne plusieurs DSA +71=Concerne plusieurs serveurs LDAP 80=Erreur inconnue 81=Impossible de contacter le serveur LDAP 85=Client délai dépassé diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/factory/JSSESocketFactory.java b/directory/java-sdk/ldapjdk/netscape/ldap/factory/JSSESocketFactory.java index 9a98538f4255..5961b22b5c11 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/factory/JSSESocketFactory.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/factory/JSSESocketFactory.java @@ -80,11 +80,11 @@ public class JSSESocketFactory } } catch (UnknownHostException e) { throw new LDAPException("SSL connection to " + host + - ":" + port, + ":" + port + ", " + e.getMessage(), LDAPException.CONNECT_ERROR); } catch (IOException f) { throw new LDAPException("SSL connection to " + host + - ":" + port, + ":" + port + ", " + f.getMessage(), LDAPException.CONNECT_ERROR); } diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/util/ConnectionPool.java b/directory/java-sdk/ldapjdk/netscape/ldap/util/ConnectionPool.java index cff63d71100e..64db4ddf449a 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/util/ConnectionPool.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/util/ConnectionPool.java @@ -193,7 +193,43 @@ public class ConnectionPool { } return con; } - + + /** + * Gets a connection from the pool within a time limit. + * + * If no connections are available, the pool will be + * extended if the number of connections is less than + * the maximum; if the pool cannot be extended, the method + * blocks until a free connection becomes available or the + * time limit is exceeded. + * + * @param timeout timeout in milliseconds + * @return an active connection or null if timed out. + */ + public LDAPConnection getConnection(int timeout) { + LDAPConnection con; + + while( (con = getConnFromPool()) == null ) { + long t1, t0 = System.currentTimeMillis(); + + if (timeout <= 0) { + return con; + } + + synchronized( pool ) { + try { + pool.wait(timeout); + } catch ( InterruptedException e ) { + return null; + } + } + + t1 = System.currentTimeMillis(); + timeout -= (t1 - t0); + } + return con; + } + /** * Gets a connection from the pool * diff --git a/directory/java-sdk/ldapjdk/netscape/ldap/util/DSMLWriter.java b/directory/java-sdk/ldapjdk/netscape/ldap/util/DSMLWriter.java index 88ff4e8397c5..4ff9344a3795 100644 --- a/directory/java-sdk/ldapjdk/netscape/ldap/util/DSMLWriter.java +++ b/directory/java-sdk/ldapjdk/netscape/ldap/util/DSMLWriter.java @@ -94,13 +94,13 @@ public class DSMLWriter extends LDAPWriter { while( attrs.hasMoreElements() ) { printString( " " ); + "\" required=\"true\"/>" ); } attrs = s.getOptionalAttributes(); while( attrs.hasMoreElements() ) { printString( " " ); + "\" required=\"false\"/>" ); } printString( " " ); }