diff --git a/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java b/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java index 320b0c08..62b3e258 100644 --- a/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java +++ b/core/src/main/java/org/springframework/ldap/support/LdapEncoder.java @@ -17,12 +17,16 @@ package org.springframework.ldap.support; import org.springframework.ldap.BadLdapGrammarException; +import org.springframework.util.Assert; + +import javax.xml.bind.DatatypeConverter; /** * Helper class to encode and decode ldap names and values. * * @author Adam Skogman * @author Mattias Hellborg Arthursson + * @author Thomas Darimont */ public final class LdapEncoder { @@ -31,6 +35,8 @@ public final class LdapEncoder { private static String[] FILTER_ESCAPE_TABLE = new String['\\' + 1]; + private static final int RFC2849_MAX_BASE64_CHARS_PER_LINE = 76; + static { // Name encoding table ------------------------------------- @@ -229,4 +235,60 @@ public final class LdapEncoder { return decoded.toString(); } + + /** + * Converts an array of bytes into a Base64 encoded string according to the rules for converting LDAP Attributes in RFC2849. + * + * @param val + * @return + * A string containing a lexical representation of base64Binary wrapped around 76 characters. + * @throws IllegalArgumentException if val is null. + */ + public static String printBase64Binary(byte[] val) { + + Assert.notNull(val, "val must not be null!"); + + String encoded = DatatypeConverter.printBase64Binary(val); + + int length = encoded.length(); + StringBuilder sb = new StringBuilder(length + length / RFC2849_MAX_BASE64_CHARS_PER_LINE); + + for (int i = 0, len = length; i < len; i++) { + sb.append(encoded.charAt(i)); + + if ((i + 1) % RFC2849_MAX_BASE64_CHARS_PER_LINE == 0) { + sb.append('\n'); + } + } + + return sb.toString(); + } + + /** + * Converts the Base64 encoded string argument into an array of bytes. + * + * @param val + * @return + * An array of bytes represented by the string argument. + * @throws IllegalArgumentException if val is null or does not conform to lexical value space defined in XML Schema Part 2: Datatypes for xsd:base64Binary. + */ + public static byte[] parseBase64Binary(String val) { + + Assert.notNull(val, "val must not be null!"); + + int length = val.length(); + StringBuilder sb = new StringBuilder(length); + for (int i = 0, len = length; i < len; i++) { + + char c = val.charAt(i); + + if(c == '\n'){ + continue; + } + + sb.append(c); + } + + return DatatypeConverter.parseBase64Binary(sb.toString()); + } } diff --git a/ldif/ldif-core/src/main/java/org/springframework/ldap/core/LdapAttributes.java b/ldif/ldif-core/src/main/java/org/springframework/ldap/core/LdapAttributes.java index 7bb871bb..67741dab 100644 --- a/ldif/ldif-core/src/main/java/org/springframework/ldap/core/LdapAttributes.java +++ b/ldif/ldif-core/src/main/java/org/springframework/ldap/core/LdapAttributes.java @@ -17,8 +17,8 @@ package org.springframework.ldap.core; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ldap.support.LdapEncoder; import org.springframework.ldap.support.LdapUtils; -import sun.misc.BASE64Encoder; import javax.naming.Name; import javax.naming.NamingEnumeration; @@ -122,7 +122,7 @@ public class LdapAttributes extends BasicAttributes { LdapName dn = getName(); if (!dn.toString().matches(SAFE_INIT_CHAR + SAFE_CHAR + "*")) { - sb.append("dn:: " + new BASE64Encoder().encode(dn.toString().getBytes()) + "\n"); + sb.append("dn:: " + LdapEncoder.printBase64Binary(dn.toString().getBytes()) + "\n"); } else { sb.append("dn: " + getDN() + "\n"); } @@ -140,8 +140,8 @@ public class LdapAttributes extends BasicAttributes { sb.append(attribute.getID() + ": " + (String) value + "\n"); } else if (value instanceof byte[]) { - sb.append(attribute.getID() + ":: " + new BASE64Encoder().encode((byte[]) value) + "\n"); - + sb.append(attribute.getID() + ":: " + LdapEncoder.printBase64Binary((byte[]) value) + "\n"); + } else if (value instanceof URI) { sb.append(attribute.getID() + ":< " + (URI) value + "\n"); diff --git a/ldif/ldif-core/src/main/java/org/springframework/ldap/ldif/support/DefaultAttributeValidationPolicy.java b/ldif/ldif-core/src/main/java/org/springframework/ldap/ldif/support/DefaultAttributeValidationPolicy.java index d83121f1..b43f2336 100644 --- a/ldif/ldif-core/src/main/java/org/springframework/ldap/ldif/support/DefaultAttributeValidationPolicy.java +++ b/ldif/ldif-core/src/main/java/org/springframework/ldap/ldif/support/DefaultAttributeValidationPolicy.java @@ -19,10 +19,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ldap.core.LdapAttribute; import org.springframework.ldap.ldif.InvalidAttributeFormatException; +import org.springframework.ldap.support.LdapEncoder; import org.springframework.util.StringUtils; -import sun.misc.BASE64Decoder; import javax.naming.directory.Attribute; +import javax.xml.bind.DatatypeConverter; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -337,11 +338,11 @@ public class DefaultAttributeValidationPolicy implements AttributeValidationPoli List options = Arrays.asList((StringUtils.isEmpty(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR))); if (options.isEmpty()) { - return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), ordered); + return new LdapAttribute(id, LdapEncoder.parseBase64Binary(value), ordered); } else { - return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), options, ordered); + return new LdapAttribute(id, LdapEncoder.parseBase64Binary(value), options, ordered); } - } catch (IOException e) { + } catch (IllegalArgumentException e) { throw new InvalidAttributeFormatException(e); } } diff --git a/ldif/ldif-core/src/main/java/org/springframework/ldap/schema/BasicSchemaSpecification.java b/ldif/ldif-core/src/main/java/org/springframework/ldap/schema/BasicSchemaSpecification.java index 58cda516..b35bff5c 100644 --- a/ldif/ldif-core/src/main/java/org/springframework/ldap/schema/BasicSchemaSpecification.java +++ b/ldif/ldif-core/src/main/java/org/springframework/ldap/schema/BasicSchemaSpecification.java @@ -1,7 +1,7 @@ package org.springframework.ldap.schema; import org.springframework.ldap.core.LdapAttributes; -import sun.misc.BASE64Encoder; +import org.springframework.ldap.support.LdapEncoder; import javax.naming.NamingException; import javax.naming.ldap.LdapName; @@ -49,9 +49,8 @@ public class BasicSchemaSpecification implements Specification { return true; } } else if(object instanceof byte[]) { - BASE64Encoder encoder = new BASE64Encoder(); - String rdnValue = encoder.encode(((String)rdn.getValue()).getBytes()); - String attributeValue = encoder.encode((byte[]) object); + String rdnValue = LdapEncoder.printBase64Binary(((String)rdn.getValue()).getBytes()); + String attributeValue = LdapEncoder.printBase64Binary((byte[]) object); if (rdnValue.equals(attributeValue)) return true; } } diff --git a/ldif/ldif-core/src/test/java/org/springframework/ldap/ldif/DefaultAttributeValidationPolicyTest.java b/ldif/ldif-core/src/test/java/org/springframework/ldap/ldif/DefaultAttributeValidationPolicyTest.java index de178440..37dc66e3 100644 --- a/ldif/ldif-core/src/test/java/org/springframework/ldap/ldif/DefaultAttributeValidationPolicyTest.java +++ b/ldif/ldif-core/src/test/java/org/springframework/ldap/ldif/DefaultAttributeValidationPolicyTest.java @@ -24,8 +24,8 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import org.springframework.ldap.core.LdapAttribute; import org.springframework.ldap.ldif.support.DefaultAttributeValidationPolicy; +import org.springframework.ldap.support.LdapEncoder; import org.springframework.util.StringUtils; -import sun.misc.BASE64Decoder; import java.net.URI; import java.util.Arrays; @@ -151,7 +151,7 @@ public class DefaultAttributeValidationPolicyTest { break; case BASE64: - byte[] bytes = new BASE64Decoder().decodeBuffer(value); + byte[] bytes = LdapEncoder.parseBase64Binary(value); assertTrue("Value is not a byte[].", attribute.get() instanceof byte[]); assertArrayEquals("Values do not match: ", bytes, (byte[]) attribute.get()); break;