You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2008/07/10 13:22:52 UTC
svn commit: r675519 - in /directory:
apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/
apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/
shared/trunk/ldap/src/main/java/org/apache/directory/s...
Author: elecharny
Date: Thu Jul 10 04:22:50 2008
New Revision: 675519
URL: http://svn.apache.org/viewvc?rev=675519&view=rev
Log:
Fix for DIRSERVER-1196 (escaped chars in a filter are not un-escaped)
Modified:
directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java
directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/NormalizingVisitor.java
directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java
Modified: directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java?rev=675519&r1=675518&r2=675519&view=diff
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java (original)
+++ directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/jndi/SearchIT.java Thu Jul 10 04:22:50 2008
@@ -1213,6 +1213,56 @@
assertFalse( results.contains( "cn=testGroup4,ou=groups,ou=system" ) );
assertTrue( results.contains( "cn=testGroup5,ou=groups,ou=system" ) );
}
+
+
+ @Test
+ public void testSearchWithEscapedCharsInFilter() throws NamingException
+ {
+ // Create an entry with special chars in the description attribute
+ LdapContext sysRoot = getSystemContext( service );
+ // Create entry cn=Sid Vicious, ou=system
+ Attributes vicious = new AttributesImpl();
+ Attribute ocls = new AttributeImpl( "objectClass" );
+ ocls.add( "top" );
+ ocls.add( "person" );
+ vicious.put( ocls );
+ vicious.put( "cn", "Sid Vicious" );
+ vicious.put( "sn", "Vicious" );
+ vicious.put( "description", "(sex pistols)" );
+ DirContext ctx = sysRoot.createSubcontext( "cn=Sid Vicious", vicious );
+ assertNotNull( ctx );
+
+ ctx = ( DirContext ) sysRoot.lookup( "cn=Sid Vicious" );
+ assertNotNull( ctx );
+
+ Attributes attributes = ctx.getAttributes( "" );
+
+ assertEquals( "(sex pistols)", attributes.get( "description" ).get() );
+
+ // Now, search for the description
+ SearchControls controls = new SearchControls();
+ controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+ controls.setDerefLinkFlag( false );
+ controls.setReturningAttributes( new String[] { "*" } );
+ sysRoot.addToEnvironment( JndiPropertyConstants.JNDI_LDAP_DAP_DEREF_ALIASES,
+ AliasDerefMode.NEVER_DEREF_ALIASES.getJndiValue() );
+ HashMap<String, Attributes> map = new HashMap<String, Attributes>();
+
+ NamingEnumeration<SearchResult> list = sysRoot.search( "", "(description=\\28sex pistols\\29)", controls );
+
+ while ( list.hasMore() )
+ {
+ SearchResult result = list.next();
+ map.put( result.getName(), result.getAttributes() );
+ }
+
+ assertEquals( "Expected number of results returned was incorrect!", 1, map.size() );
+
+ Attributes attrs = map.get( "cn=Sid Vicious,ou=system" );
+
+ assertNotNull( attrs.get( "objectClass" ) );
+ assertNotNull( attrs.get( "cn" ) );
+ }
/**
Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/NormalizingVisitor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/NormalizingVisitor.java?rev=675519&r1=675518&r2=675519&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/NormalizingVisitor.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/normalization/NormalizingVisitor.java Thu Jul 10 04:22:50 2008
@@ -23,6 +23,7 @@
import java.util.ArrayList;
import java.util.List;
+import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import org.apache.directory.server.schema.registries.Registries;
@@ -41,6 +42,7 @@
import org.apache.directory.shared.ldap.filter.SubstringNode;
import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.util.ByteBuffer;
import org.apache.directory.shared.ldap.util.StringTools;
import org.slf4j.Logger;
@@ -77,6 +79,30 @@
/**
+ * Chars which need to be escaped in a filter
+ * '\0' | '(' | ')' | '*' | '\'
+ */
+ private static final boolean[] FILTER_CHAR =
+ {
+ true, false, false, false, false, false, false, false, // 00 -> 07 NULL
+ false, false, false, false, false, false, false, false, // 08 -> 0F
+ false, false, false, false, false, false, false, false, // 10 -> 17
+ false, false, false, false, false, false, false, false, // 18 -> 1F
+ false, false, false, false, false, false, false, false, // 20 -> 27
+ true, true, true, false, false, false, false, false, // 28 -> 2F '(', ')', '*'
+ false, false, false, false, false, false, false, false, // 30 -> 37
+ false, false, false, false, false, false, false, false, // 38 -> 3F
+ false, false, false, false, false, false, false, false, // 40 -> 47
+ false, false, false, false, false, false, false, false, // 48 -> 4F
+ false, false, false, false, false, false, false, false, // 50 -> 57
+ false, false, false, false, true, false, false, false, // 58 -> 5F '\'
+ false, false, false, false, false, false, false, false, // 60 -> 67
+ false, false, false, false, false, false, false, false, // 68 -> 6F
+ false, false, false, false, false, false, false, false, // 70 -> 77
+ false, false, false, false, false, false, false, false // 78 -> 7F
+ };
+
+ /**
*
* Creates a new instance of NormalizingVisitor.
*
@@ -91,6 +117,118 @@
/**
+ * Check if the given char is a filter escaped char
+ * <filterEscapedChars> ::= '\0' | '(' | ')' | '*' | '\'
+ *
+ * @param c the char we want to test
+ * @return true if the char is a pair char only
+ */
+ public static boolean isFilterChar( char c )
+ {
+ return ( ( ( c | 0x7F ) == 0x7F ) && FILTER_CHAR[c & 0x7f] );
+ }
+
+ /**
+ * Decodes sequences of escaped hex within an attribute's value into
+ * a UTF-8 String. The hex is decoded inline and the complete decoded
+ * String is returned.
+ *
+ * @param str the string containing hex escapes
+ * @return the decoded string
+ */
+ private static final String decodeEscapedHex( String str ) throws InvalidNameException
+ {
+ // create buffer and add everything before start of scan
+ StringBuffer buf = new StringBuffer();
+ ByteBuffer bb = new ByteBuffer();
+ boolean escaped = false;
+
+ // start scanning until we find an escaped series of bytes
+ for ( int ii = 0; ii < str.length(); ii++ )
+ {
+ char c = str.charAt( ii );
+
+ if ( c == '\\' )
+ {
+ // we have the start of a hex escape sequence
+ if ( StringTools.isHex( str, ii+1 ) && StringTools.isHex ( str, ii+2 ) )
+ {
+ bb.clear();
+ int advancedBy = StringTools.collectEscapedHexBytes( bb, str, ii );
+ ii+=advancedBy-1;
+ buf.append( StringTools.utf8ToString( bb.buffer(), bb.position() ) );
+ escaped = false;
+ continue;
+ }
+ else if ( !escaped )
+ {
+ // It may be an escaped char ( '\0', '(', ')', '*', '\' )
+ escaped = true;
+ continue;
+ }
+ }
+
+
+ if ( escaped )
+ {
+ if ( isFilterChar( c ) )
+ {
+ // It is an escaped char ( '\0', '(', ')', '*', '\' )
+ // Stores it into the buffer without the '\'
+ escaped = false;
+ buf.append( c );
+ continue;
+ }
+ else
+ {
+ throw new InvalidNameException( "The value must contain valid escaped characters." );
+ }
+ }
+ else
+ {
+ buf.append( str.charAt( ii ) );
+ }
+ }
+
+ if ( escaped )
+ {
+ // We should not have a '\' at the end of the string
+ throw new InvalidNameException( "The value must not ends with a '\\'." );
+ }
+
+ return buf.toString();
+ }
+
+
+ /**
+ * Un escape the escaped chars in the value
+ */
+ private void unescapeValue( Value<?> value )
+ {
+ if ( !value.isBinary() )
+ {
+ String valStr = (String)value.getNormalizedValue();
+
+ if ( StringTools.isEmpty( valStr ) )
+ {
+ return;
+ }
+
+ try
+ {
+ String newStr= decodeEscapedHex( valStr );
+ ((ClientStringValue)value).set( newStr );
+ return;
+ }
+ catch ( InvalidNameException ine )
+ {
+ value.set( null );
+ return;
+ }
+ }
+ }
+
+ /**
* A private method used to normalize a value
*
* @param attribute The attribute's ID
@@ -111,11 +249,15 @@
{
normalized = new ClientStringValue( ( String ) ncn.normalizeByName( attribute, StringTools
.utf8ToString( ( byte[] ) value.get() ) ) );
+
+ unescapeValue( normalized );
}
else
{
normalized = new ClientStringValue( ( String ) ncn.normalizeByName( attribute, ( String ) value
.get() ) );
+
+ unescapeValue( normalized );
}
}
else
Modified: directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java?rev=675519&r1=675518&r2=675519&view=diff
==============================================================================
--- directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java (original)
+++ directory/shared/trunk/ldap/src/main/java/org/apache/directory/shared/ldap/util/StringTools.java Thu Jul 10 04:22:50 2008
@@ -3446,7 +3446,17 @@
}
- private static int collectEscapedHexBytes( ByteBuffer bb, String str, int index )
+ /**
+ * Collects an hex sequence from a string, and returns the value
+ * as an integer, after having modified the initial value (the escaped
+ * hex value is transsformed to the byte it represents).
+ *
+ * @param bb the buffer which will contain the unescaped byte
+ * @param str the initial string with ecaped chars
+ * @param index the position in the string of the escaped data
+ * @return the byte as an integer
+ */
+ public static int collectEscapedHexBytes( ByteBuffer bb, String str, int index )
{
int advanceBy = 0;