You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2012/11/04 12:53:00 UTC
svn commit: r1405534 - in /directory/shared/trunk/ldap/model/src:
main/java/org/apache/directory/shared/ldap/model/filter/
test/java/org/apache/directory/shared/ldap/model/filter/
Author: seelmann
Date: Sun Nov 4 11:52:59 2012
New Revision: 1405534
URL: http://svn.apache.org/viewvc?rev=1405534&view=rev
Log:
Fix for DIRSHARED-143 (Provide helper method to escape characters to be used in LDAP Filter literal)
Added:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/FilterEncoder.java
directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/shared/ldap/model/filter/FilterEncoderTest.java
Modified:
directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/AbstractExprNode.java
Modified: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/AbstractExprNode.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/AbstractExprNode.java?rev=1405534&r1=1405533&r2=1405534&view=diff
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/AbstractExprNode.java (original)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/AbstractExprNode.java Sun Nov 4 11:52:59 2012
@@ -205,51 +205,15 @@ public abstract class AbstractExprNode i
}
val = ( ( StringValue ) value ).getString();
-
- for ( int i = 0; i < val.length(); i++ )
+ String encodedVal = FilterEncoder.encodeFilterValue( val );
+ if ( val.equals( encodedVal ) )
{
- char ch = val.charAt( i );
- String replace = null;
-
- switch ( ch )
- {
- case '*':
- replace = "\\2A";
- break;
-
- case '(':
- replace = "\\28";
- break;
-
- case ')':
- replace = "\\29";
- break;
-
- case '\\':
- replace = "\\5C";
- break;
-
- case '\0':
- replace = "\\00";
- break;
- }
-
- if ( replace != null )
- {
- if ( sb == null )
- {
- sb = new StringBuilder( val.length() * 2 );
- sb.append( val.substring( 0, i ) );
- }
- sb.append( replace );
- }
- else if ( sb != null )
- {
- sb.append( ch );
- }
+ return value;
+ }
+ else
+ {
+ return new StringValue( encodedVal );
}
-
- return ( sb == null ? value : new StringValue( sb.toString() ) );
}
Added: directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/FilterEncoder.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/FilterEncoder.java?rev=1405534&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/FilterEncoder.java (added)
+++ directory/shared/trunk/ldap/model/src/main/java/org/apache/directory/shared/ldap/model/filter/FilterEncoder.java Sun Nov 4 11:52:59 2012
@@ -0,0 +1,133 @@
+/*
+ * 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.shared.ldap.model.filter;
+
+
+import java.text.Format;
+import java.text.MessageFormat;
+
+
+/**
+ * An encoder for LDAP filters.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterEncoder
+{
+ private static final String[] EMPTY = new String[0];
+
+
+ /**
+ * Formats a filter and handles encoding of special characters in the value arguments using the
+ * <valueencoding> rule as described in <a href="http://www.ietf.org/rfc/rfc4515.txt">RFC 4515</a>.
+ *
+ * @param filterTemplate the filter with placeholders
+ * @param values the values to encode and substitute
+ * @return the formatted filter with escaped values
+ * @throws IllegalArgumentException if the number of values does not match the number of placeholders in the template
+ */
+ public static String format( String filterTemplate, String[] values ) throws IllegalArgumentException
+ {
+ if ( values == null )
+ {
+ values = EMPTY;
+ }
+
+ MessageFormat mf = new MessageFormat( filterTemplate );
+
+ // check element count and argument count
+ Format[] formats = mf.getFormatsByArgumentIndex();
+ if ( formats.length != values.length )
+ {
+ // TODO: I18n
+ String msg = "Filter template {0} has {1} placeholders but {2} arguments provided.";
+ throw new IllegalArgumentException( MessageFormat.format( msg, filterTemplate, formats.length,
+ values.length ) );
+ }
+
+ // encode arguments
+ for ( int i = 0; i < values.length; i++ )
+ {
+ values[i] = encodeFilterValue( values[i] );
+ }
+
+ // format the filter
+ String format = mf.format( values );
+ return format;
+ }
+
+
+ /**
+ * Handles encoding of special characters in LDAP search filter assertion values using the
+ * <valueencoding> rule as described in <a href="http://www.ietf.org/rfc/rfc4515.txt">RFC 4515</a>.
+ *
+ * @param value Right hand side of "attrId=value" assertion occurring in an LDAP search filter.
+ * @return Escaped version of <code>value</code>
+ */
+ public static String encodeFilterValue( String value )
+ {
+ StringBuilder sb = null;
+
+ for ( int i = 0; i < value.length(); i++ )
+ {
+ char ch = value.charAt( i );
+ String replace = null;
+
+ switch ( ch )
+ {
+ case '*':
+ replace = "\\2A";
+ break;
+
+ case '(':
+ replace = "\\28";
+ break;
+
+ case ')':
+ replace = "\\29";
+ break;
+
+ case '\\':
+ replace = "\\5C";
+ break;
+
+ case '\0':
+ replace = "\\00";
+ break;
+ }
+
+ if ( replace != null )
+ {
+ if ( sb == null )
+ {
+ sb = new StringBuilder( value.length() * 2 );
+ sb.append( value.substring( 0, i ) );
+ }
+ sb.append( replace );
+ }
+ else if ( sb != null )
+ {
+ sb.append( ch );
+ }
+ }
+
+ return ( sb == null ? value : sb.toString() );
+ }
+}
Added: directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/shared/ldap/model/filter/FilterEncoderTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/shared/ldap/model/filter/FilterEncoderTest.java?rev=1405534&view=auto
==============================================================================
--- directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/shared/ldap/model/filter/FilterEncoderTest.java (added)
+++ directory/shared/trunk/ldap/model/src/test/java/org/apache/directory/shared/ldap/model/filter/FilterEncoderTest.java Sun Nov 4 11:52:59 2012
@@ -0,0 +1,122 @@
+/*
+ * 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.shared.ldap.model.filter;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.directory.shared.ldap.model.filter.FilterEncoder;
+import org.junit.Test;
+
+
+/**
+ * Tests for {@link FilterEncoder}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class FilterEncoderTest
+{
+
+ private static final String[] ZERO = new String[0];
+ private static final String[] ONE = new String[]
+ { "foo" };
+ private static final String[] TWO = new String[]
+ { "foo", "bar" };
+ private static final String[] SPECIAL_CHARS = new String[]
+ { "(\\*\0)" };
+
+
+ @Test
+ public void testFormatWithNoPlaceholdersAndCorrectArgumentCount()
+ {
+ assertEquals( "(cn=foo)", FilterEncoder.format( "(cn=foo)", null ) );
+ assertEquals( "(cn=foo)", FilterEncoder.format( "(cn=foo)", ZERO ) );
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFormatWithNoPlaceholdersAndTooManyArguments()
+ {
+ FilterEncoder.format( "(cn=foo)", ONE );
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFormatWithPlaceholdersAndTooFewArguments()
+ {
+ FilterEncoder.format( "(cn={0})", ZERO );
+ }
+
+
+ @Test
+ public void testFormatWithPlaceholdersAndCorrectArgumentCount()
+ {
+ assertEquals( "(cn=foo)", FilterEncoder.format( "(cn={0})", ONE ) );
+ assertEquals( "(&(cn=foo)(uid=bar))", FilterEncoder.format( "(&(cn={0})(uid={1}))", TWO ) );
+ }
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testFormatWithPlaceholdersAndTooManyArguments()
+ {
+ FilterEncoder.format( "(cn={0})", TWO );
+ }
+
+
+ @Test
+ public void testFormatWithPlaceholdersAndSpecialChars()
+ {
+ assertEquals( "(cn=\\28\\5C\\2A\\00\\29)", FilterEncoder.format( "(cn={0})", SPECIAL_CHARS ) );
+ }
+
+
+ @Test
+ public void testExceptionMessage()
+ {
+ try
+ {
+ FilterEncoder.format( "(&(cn={0})(uid={1}))", ONE );
+ fail( "IllegalArgumentException expected" );
+ }
+ catch ( IllegalArgumentException e )
+ {
+ String message = e.getMessage();
+ assertTrue( message.contains( " (&(cn={0})(uid={1})) " ) );
+ assertTrue( message.contains( " 2 " ) );
+ assertTrue( message.contains( " 1 " ) );
+ }
+ }
+
+
+ @Test
+ public void testEncodeFilterValue()
+ {
+ assertEquals( "1234567890", FilterEncoder.encodeFilterValue( "1234567890" ) );
+ assertEquals( "\\28", FilterEncoder.encodeFilterValue( "(" ) );
+ assertEquals( "\\29", FilterEncoder.encodeFilterValue( ")" ) );
+ assertEquals( "\\2A", FilterEncoder.encodeFilterValue( "*" ) );
+ assertEquals( "\\5C", FilterEncoder.encodeFilterValue( "\\" ) );
+ assertEquals( "\\00", FilterEncoder.encodeFilterValue( "\0" ) );
+ assertEquals( "\\28\\2A\\29", FilterEncoder.encodeFilterValue( "(*)" ) );
+ }
+
+}