Index: ldap/pom.xml =================================================================== --- ldap/pom.xml (revision 389684) +++ ldap/pom.xml (working copy) @@ -83,6 +83,12 @@ + commons-io + commons-io + 1.2 + + + org.apache.directory.shared shared-asn1 ${pom.version} Index: ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifParserImpl.java =================================================================== --- ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifParserImpl.java (revision 389684) +++ ldap/src/main/java/org/apache/directory/shared/ldap/ldif/LdifParserImpl.java (working copy) @@ -18,9 +18,11 @@ package org.apache.directory.shared.ldap.ldif; -import java.io.IOException; -import java.io.StringReader; -import java.io.BufferedReader; +import java.io.*; +import java.net.URL; +import java.net.MalformedURLException; +import java.util.regex.Pattern; +import java.util.regex.Matcher; import javax.naming.NamingException; import javax.naming.directory.Attributes; @@ -30,6 +32,7 @@ import org.apache.directory.shared.ldap.exception.LdapNamingException; import org.apache.directory.shared.ldap.message.ResultCodeEnum; import org.apache.directory.shared.ldap.util.Base64; +import org.apache.commons.io.IOUtils; /** @@ -47,6 +50,9 @@ */ public class LdifParserImpl implements LdifParser { + public static final Pattern STRING_ENCODE_PATTERN + = Pattern.compile("(string_encoding=([^;]+);\\s*)?(.+)"); + /** * Decodes an encoded string in base64 into a byte array. * @@ -75,6 +81,7 @@ */ public synchronized void parse( Attributes attributes, String ldif ) throws NamingException { + boolean isImportFile = false; boolean isBase64Encoded = false; int lineCount = 0; int index; @@ -122,22 +129,24 @@ continue; } - // Consume next char and check if it's a colon for binary attr. - if ( line.charAt( ++index ) == ':' ) - { + // Consume next char and check if it's a colon for binary attr + // or '<' for file inclusion + index++; + if ( line.charAt( index ) == ':' ) isBase64Encoded = true; - } + else if ( line.charAt( index ) == '<' ) + isImportFile = true; // Advance index past whitespace to the first char of the value. try { - while ( ( line.length() <= index + 1 ) && line.charAt( ++index ) == ' ' ) + while ( ( ++index < line.length() - 1 ) && line.charAt( index ) == ' ' ) { ; // Does nothing! } // Capture attribute value from first char till end of line. - attrValue = line.substring( index + 1 ); + attrValue = line.substring( index ); } catch ( StringIndexOutOfBoundsException e ) { @@ -165,6 +174,72 @@ } isBase64Encoded = false; } + else if ( isImportFile && ( attrValue != null ) ) + { + final URL url; + final Matcher matcher; + final String stringEncoding; + final String urlStr; + InputStream is = null; + StringWriter sw = null; + ByteArrayOutputStream bos = null; + final Object value; + + matcher = STRING_ENCODE_PATTERN.matcher(attrValue); + matcher.matches(); + stringEncoding = matcher.group(2); + urlStr = matcher.group(3); + + try + { + url = new URL(urlStr); + is = url.openStream(); + if (stringEncoding != null) + { + sw = new StringWriter(4 * 1024); + IOUtils.copy(is, sw, stringEncoding); + value = sw.toString(); + } + else + { + bos = new ByteArrayOutputStream(4 * 1024); + IOUtils.copy(is, bos); + value = bos.toByteArray(); + } + } + catch (MalformedURLException e) + { + throw new LdapNamingException( "Line " + lineCount + " [" + line + + "] passes malformed URL to ':<' inclusion.\n{" + ldif + "}", + ResultCodeEnum.OTHER ); + } + catch (IOException e) + { + throw new LdapNamingException( "Line " + lineCount + " [" + line + + "] failed including URL passed to ':<' inclusion.\n{" + ldif + "}", + ResultCodeEnum.OTHER ); + } + finally + { + if (is != null) + try { is.close(); } catch (IOException e) {} + if (sw != null) + try { sw.close(); } catch (IOException e) {} + if (bos != null) + try { bos.close(); } catch (IOException e) {} + } + + if ( attributes.get( attrName ) == null ) + { + attributes.put( attrName, value ); + } + else + { + Attribute attribute = attributes.get( attrName ); + attribute.add( value ); + } + isImportFile = false; + } else { if ( attributes.get( attrName ) == null ) Index: ldap/src/test/resources/test_inclusion.ldif =================================================================== --- ldap/src/test/resources/test_inclusion.ldif (revision 0) +++ ldap/src/test/resources/test_inclusion.ldif (revision 0) @@ -0,0 +1,6 @@ +# attribute is stored as byte[] +httpurl:< http://isis/public/hopno02/jx.txt +# attribute is stored as byte[] +fileurl:< file:///D:/src/ad/shared/ldap/src/test/resources/test_ldif_inclusion.txt +# attribute is stored as UTF8 encoded String +strfileurl:< string_encoding=UTF8;file:///D:/src/ad/shared/ldap/src/test/resources/test_ldif_inclusion.txt Index: ldap/src/test/resources/test_ldif_inclusion.txt =================================================================== --- ldap/src/test/resources/test_ldif_inclusion.txt (revision 0) +++ ldap/src/test/resources/test_ldif_inclusion.txt (revision 0) @@ -0,0 +1,4 @@ + +multiple +lines + \ No newline at end of file