protected static function _parseCombination($filter)
{
// Extract logical operator and filter arguments.
$operator = substr($filter, 0, 1);
$filter = substr($filter, 1);
// Split $filter into individual subfilters. We cannot use split() for
// this, because we do not know the complexiness of the
// subfilter. Thus, we look trough the filter string and just recognize
// ending filters at the first level. We record the index number of the
// char and use that information later to split the string.
$sub_index_pos = array();
// Previous character looked at.
$prev_char = '';
// Denotes the current bracket level we are, >1 is too deep, 1 is ok, 0
// is outside any subcomponent.
$level = 0;
for ($curpos = 0, $len = strlen($filter); $curpos < $len; $curpos++) {
$cur_char = $filter[$curpos];
// Rise/lower bracket level.
if ($cur_char == '(' && $prev_char != '\\') {
$level++;
} elseif ($cur_char == ')' && $prev_char != '\\') {
$level--;
}
if ($cur_char == '(' && $prev_char == ')' && $level == 1) {
// Mark the position for splitting.
$sub_index_pos[] = $curpos;
}
$prev_char = $cur_char;
}
// Now perform the splits. To get the last part too, we need to add the
// "END" index to the split array.
$sub_index_pos[] = strlen($filter);
$subfilters = array();
$oldpos = 0;
foreach ($sub_index_pos as $s_pos) {
$str_part = substr($filter, $oldpos, $s_pos - $oldpos);
$subfilters[] = $str_part;
$oldpos = $s_pos;
}
if (count($subfilters) > 1) {
// Several subfilters found.
if ($operator == '!') {
throw new Horde_Ldap_Exception('Invalid filter syntax: NOT operator detected but several arguments given');
}
} elseif (!count($subfilters)) {
// This should not happen unless the user specified a wrong filter.
throw new Horde_Ldap_Exception('Invalid filter syntax: got operator ' . $operator . ' but no argument');
}
// Now parse the subfilters into objects and combine them using the
// operator.
$subfilters_o = array();
foreach ($subfilters as $s_s) {
$subfilters_o[] = self::parse($s_s);
}
if (count($subfilters_o) == 1) {
$subfilters_o = $subfilters_o[0];
}
return self::combine($operator, $subfilters_o);
}