Skip to content

Commit

Permalink
Better handle empty comps in substring filters
Browse files Browse the repository at this point in the history
Updated the Filter methods for creating substring filters to better
support empty components.  In LDAP filters, filters are transmitted
using a binary encoding, and substring components may be absent but
not empty.  However, because developers creating LDAP-enabled
applications are more likely to be familiar with the string
representations of filters, it is understandable if someone were to
try to provide an empty string instead of null to indicate that the
component is not needed.  The methods for creating substring filters
will now interpret empty components as equivalent to being null,
causing them to be omitted from the resulting encoded LDAP filter.
  • Loading branch information
dirmgr committed Oct 2, 2023
1 parent 3dd7837 commit a2d25c2
Show file tree
Hide file tree
Showing 3 changed files with 348 additions and 29 deletions.
25 changes: 25 additions & 0 deletions docs/release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@

<h2>Release Notes</h2>

<h3>Version 6.0.11</h3>

<p>
The following changes were made between the 6.0.10 and 6.0.11 releases:
</p>

<ul>
<li>
Updated the Filter methods for creating substring filters to better support empty
components. In LDAP filters, filters are transmitted using a binary encoding,
and substring components may be absent but not empty. However, because
developers creating LDAP-enabled applications are more likely to be familiar with
the string representations of filters, it is understandable if someone were to
try to provide an empty string instead of null to indicate that the component is
not needed. The methods for creating substring filters will now interpret empty
components as equivalent to being null, causing them to be omitted from the
resulting encoded LDAP filter.
<br><br>
</li>
</ul>

<p></p>



<h3>Version 6.0.10</h3>

<p>
Expand Down
129 changes: 100 additions & 29 deletions src/com/unboundid/ldap/sdk/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -806,9 +806,14 @@ static Filter createEqualityFilter(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It may be {@code null} if there is no subInitial
* component, but it must not be empty.
* @param subAny The set of subAny components for this substring
* filter.
* filter. It may be {@code null} or empty if there
* are no subAny components.
* @param subFinal The subFinal component for this substring filter.
* It may be {@code null} if there is no subFinal
* component, but it must not be empty.
*
* @return The created substring search filter.
*/
Expand All @@ -835,9 +840,14 @@ public static Filter substring(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It may be {@code null} if there is no subInitial
* component, but it must not be empty.
* @param subAny The set of subAny components for this substring
* filter.
* filter. It may be {@code null} or empty if there
* are no subAny components.
* @param subFinal The subFinal component for this substring filter.
* It may be {@code null} if there is no subFinal
* component, but it must not be empty.
*
* @return The created substring search filter.
*/
Expand All @@ -860,9 +870,14 @@ public static Filter substring(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It may be {@code null} if there is no subInitial
* component, but it must not be empty.
* @param subAny The set of subAny components for this substring
* filter.
* filter. It may be {@code null} or empty if there
* are no subAny components.
* @param subFinal The subFinal component for this substring filter.
* It may be {@code null} if there is no subFinal
* component, but it must not be empty.
*
* @return The created substring search filter.
*/
Expand All @@ -874,12 +889,16 @@ public static Filter createSubstringFilter(
@Nullable final String subFinal)
{
Validator.ensureNotNull(attributeName);
Validator.ensureTrue((subInitial != null) ||
((subAny != null) && (subAny.length > 0)) ||
(subFinal != null));
Validator.ensureTrue(
(((subInitial != null) && (subInitial.length() > 0)) ||
((subAny != null) && (subAny.length > 0) &&
(subAny[0].length() > 0)) ||
((subFinal != null) && (subFinal.length() > 0))),
"At least one substring filter component must be non-null and " +
"non-empty");

final ASN1OctetString subInitialOS;
if (subInitial == null)
if ((subInitial == null) || subInitial.isEmpty())
{
subInitialOS = null;
}
Expand All @@ -895,15 +914,34 @@ public static Filter createSubstringFilter(
}
else
{
subAnyArray = new ASN1OctetString[subAny.length];
for (int i=0; i < subAny.length; i++)
if (subAny.length == 1)
{
if (subAny[0].length() == 0)
{
subAnyArray = NO_SUB_ANY;
}
else
{
subAnyArray = new ASN1OctetString[]
{
new ASN1OctetString(subAny[0])
};
}
}
else
{
subAnyArray[i] = new ASN1OctetString(subAny[i]);
subAnyArray = new ASN1OctetString[subAny.length];
for (int i=0; i < subAny.length; i++)
{
Validator.ensureFalse(subAny[i].isEmpty(),
"Individual substring filter components must not be empty");
subAnyArray[i] = new ASN1OctetString(subAny[i]);
}
}
}

final ASN1OctetString subFinalOS;
if (subFinal == null)
if ((subFinal == null) || subFinal.isEmpty())
{
subFinalOS = null;
}
Expand All @@ -927,9 +965,14 @@ public static Filter createSubstringFilter(
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It may be {@code null} if there is no subInitial
* component, but it must not be empty.
* @param subAny The set of subAny components for this substring
* filter.
* filter. It may be {@code null} or empty if there
* are no subAny components.
* @param subFinal The subFinal component for this substring filter.
* It may be {@code null} if there is no subFinal
* component, but it must not be empty.
*
* @return The created substring search filter.
*/
Expand All @@ -941,12 +984,16 @@ public static Filter createSubstringFilter(
@Nullable final byte[] subFinal)
{
Validator.ensureNotNull(attributeName);
Validator.ensureTrue((subInitial != null) ||
((subAny != null) && (subAny.length > 0)) ||
(subFinal != null));
Validator.ensureTrue(
(((subInitial != null) && (subInitial.length > 0)) ||
((subAny != null) && (subAny.length > 0) &&
(subAny[0].length > 0)) ||
((subFinal != null) && (subFinal.length > 0))),
"At least one substring filter component must be non-null and " +
"non-empty");

final ASN1OctetString subInitialOS;
if (subInitial == null)
if ((subInitial == null) || (subInitial.length == 0))
{
subInitialOS = null;
}
Expand All @@ -962,15 +1009,34 @@ public static Filter createSubstringFilter(
}
else
{
subAnyArray = new ASN1OctetString[subAny.length];
for (int i=0; i < subAny.length; i++)
if (subAny.length == 1)
{
subAnyArray[i] = new ASN1OctetString(subAny[i]);
if (subAny[0].length == 0)
{
subAnyArray = NO_SUB_ANY;
}
else
{
subAnyArray = new ASN1OctetString[]
{
new ASN1OctetString(subAny[0])
};
}
}
else
{
subAnyArray = new ASN1OctetString[subAny.length];
for (int i=0; i < subAny.length; i++)
{
Validator.ensureTrue((subAny[i].length > 0),
"Individual substring filter components must not be empty");
subAnyArray[i] = new ASN1OctetString(subAny[i]);
}
}
}

final ASN1OctetString subFinalOS;
if (subFinal == null)
if ((subFinal == null) || (subFinal.length == 0))
{
subFinalOS = null;
}
Expand All @@ -994,9 +1060,14 @@ public static Filter createSubstringFilter(
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It may be {@code null} if there is no subInitial
* component, but it must not be empty.
* @param subAny The set of subAny components for this substring
* filter.
* filter. It may be {@code null} or empty if there
* are no subAny components.
* @param subFinal The subFinal component for this substring filter.
* It may be {@code null} if there is no subFinal
* component, but it must not be empty.
*
* @return The created substring search filter.
*/
Expand Down Expand Up @@ -1038,7 +1109,7 @@ static Filter createSubstringFilter(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1062,7 +1133,7 @@ public static Filter subInitial(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1082,7 +1153,7 @@ public static Filter subInitial(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1103,7 +1174,7 @@ public static Filter createSubInitialFilter(
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subInitial The subInitial component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand Down Expand Up @@ -1216,7 +1287,7 @@ public static Filter createSubAnyFilter(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subFinal The subFinal component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1240,7 +1311,7 @@ public static Filter subFinal(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subFinal The subFinal component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1260,7 +1331,7 @@ public static Filter subFinal(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subFinal The subFinal component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand All @@ -1280,7 +1351,7 @@ public static Filter createSubFinalFilter(@NotNull final String attributeName,
* @param attributeName The attribute name for this substring filter. It
* must not be {@code null}.
* @param subFinal The subFinal component for this substring filter.
* It must not be {@code null}.
* It must not be {@code null} or empty.
*
* @return The created substring search filter.
*/
Expand Down

0 comments on commit a2d25c2

Please sign in to comment.