1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * 19 */ 20 package org.apache.directory.api.ldap.model.filter; 21 22 23 import java.text.Format; 24 import java.text.MessageFormat; 25 26 27 /** 28 * An encoder for LDAP filters. 29 * 30 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 31 */ 32 public class FilterEncoder 33 { 34 private static final String[] EMPTY = new String[0]; 35 36 37 /** 38 * Formats a filter and handles encoding of special characters in the value arguments using the 39 * <valueencoding> rule as described in <a href="http://www.ietf.org/rfc/rfc4515.txt">RFC 4515</a>. 40 * <p> 41 * Example of filter template format: <code>(&(cn={0})(uid={1}))</code> 42 * 43 * @param filterTemplate the filter with placeholders 44 * @param values the values to encode and substitute 45 * @return the formatted filter with escaped values 46 * @throws IllegalArgumentException if the number of values does not match the number of placeholders in the template 47 */ 48 public static String format( String filterTemplate, String... values ) throws IllegalArgumentException 49 { 50 if ( values == null ) 51 { 52 values = EMPTY; 53 } 54 55 MessageFormat mf = new MessageFormat( filterTemplate ); 56 57 // check element count and argument count 58 Format[] formats = mf.getFormatsByArgumentIndex(); 59 if ( formats.length != values.length ) 60 { 61 // TODO: I18n 62 String msg = "Filter template {0} has {1} placeholders but {2} arguments provided."; 63 throw new IllegalArgumentException( MessageFormat.format( msg, filterTemplate, formats.length, 64 values.length ) ); 65 } 66 67 // encode arguments 68 for ( int i = 0; i < values.length; i++ ) 69 { 70 values[i] = encodeFilterValue( values[i] ); 71 } 72 73 // format the filter 74 String format = mf.format( values ); 75 return format; 76 } 77 78 79 /** 80 * Handles encoding of special characters in LDAP search filter assertion values using the 81 * <valueencoding> rule as described in <a href="http://www.ietf.org/rfc/rfc4515.txt">RFC 4515</a>. 82 * 83 * @param value Right hand side of "attrId=value" assertion occurring in an LDAP search filter. 84 * @return Escaped version of <code>value</code> 85 */ 86 public static String encodeFilterValue( String value ) 87 { 88 StringBuilder sb = null; 89 90 for ( int i = 0; i < value.length(); i++ ) 91 { 92 char ch = value.charAt( i ); 93 String replace = null; 94 95 switch ( ch ) 96 { 97 case '*': 98 replace = "\\2A"; 99 break; 100 101 case '(': 102 replace = "\\28"; 103 break; 104 105 case ')': 106 replace = "\\29"; 107 break; 108 109 case '\\': 110 replace = "\\5C"; 111 break; 112 113 case '\0': 114 replace = "\\00"; 115 break; 116 } 117 118 if ( replace != null ) 119 { 120 if ( sb == null ) 121 { 122 sb = new StringBuilder( value.length() * 2 ); 123 sb.append( value.substring( 0, i ) ); 124 } 125 sb.append( replace ); 126 } 127 else if ( sb != null ) 128 { 129 sb.append( ch ); 130 } 131 } 132 133 return ( sb == null ? value : sb.toString() ); 134 } 135 }