⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.89
Server IP:
41.128.143.86
Server:
Linux host.raqmix.cloud 6.8.0-1025-azure #30~22.04.1-Ubuntu SMP Wed Mar 12 15:28:20 UTC 2025 x86_64
Server Software:
Apache
PHP Version:
8.3.23
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
usr
/
share
/
psa-pear
/
pear
/
php
/
Horde
/
Ldap
/
Edit File: Filter.php
<?php /** * Object representation of a part of a LDAP filter. * * The purpose of this class is to easily build LDAP filters without having to * worry about correct escaping etc. * * A filter is built using several independent filter objects which are * combined afterwards. This object works in two modes, depending how the * object is created. * * If the object is created using the {@link create()} method, then this is a * leaf-object. If the object is created using the {@link combine()} method, * then this is a container object. * * LDAP filters are defined in RFC 2254. * * @see http://www.ietf.org/rfc/rfc2254.txt * * A short example: * <code> * $filter0 = Horde_Ldap_Filter::create('stars', 'equals', '***'); * $filter_not0 = Horde_Ldap_Filter::combine('not', $filter0); * * $filter1 = Horde_Ldap_Filter::create('gn', 'begins', 'bar'); * $filter2 = Horde_Ldap_Filter::create('gn', 'ends', 'baz'); * $filter_comp = Horde_Ldap_Filter::combine('or', array($filter_not0, $filter1, $filter2)); * * echo (string)$filter_comp; * // This will output: (|(!(stars=\0x5c0x2a\0x5c0x2a\0x5c0x2a))(gn=bar*)(gn=*baz)) * // The stars in $filter0 are treaten as real stars unless you disable escaping. * </code> * * Copyright 2009 Benedikt Hallinger * Copyright 2010-2017 Horde LLC (http://www.horde.org/) * * @category Horde * @package Ldap * @author Benedikt Hallinger <beni@php.net> * @author Jan Schneider <jan@horde.org> * @license http://www.gnu.org/licenses/lgpl-3.0.html LGPL-3.0 */ class Horde_Ldap_Filter { /** * Storage for combination of filters. * * This variable holds a array of filter objects that should be combined by * this filter object. * * @var array */ protected $_filters = array(); /** * Operator for sub-filters. * * @var string */ protected $_operator; /** * Single filter. * * If this is a leaf filter, the filter representation is store here. * * @var string */ protected $_filter; /** * Constructor. * * Construction of Horde_Ldap_Filter objects should happen through either * {@link create()} or {@link combine()} which give you more control. * However, you may use the constructor if you already have generated * filters. * * @param array $params List of object parameters */ protected function __construct(array $params) { foreach ($params as $param => $value) { if (in_array($param, array('filter', 'filters', 'operator'))) { $this->{'_' . $param} = $value; } } } /** * Creates a new part of an LDAP filter. * * The following matching rules exists: * - equals: One of the attributes values is exactly $value. * Please note that case sensitiviness depends on the * attributes syntax configured in the server. * - begins: One of the attributes values must begin with $value. * - ends: One of the attributes values must end with $value. * - contains: One of the attributes values must contain $value. * - present | any: The attribute can contain any value but must exist. * - greater: The attributes value is greater than $value. * - less: The attributes value is less than $value. * - greaterOrEqual: The attributes value is greater or equal than $value. * - lessOrEqual: The attributes value is less or equal than $value. * - approx: One of the attributes values is similar to $value. * * If $escape is set to true then $value will be escaped. If set to false * then $value will be treaten as a raw filter value string. You should * then escape it yourself using {@link * Horde_Ldap_Util::escapeFilterValue()}. * * Examples: * <code> * // This will find entries that contain an attribute "sn" that ends with * // "foobar": * $filter = Horde_Ldap_Filter::create('sn', 'ends', 'foobar'); * * // This will find entries that contain an attribute "sn" that has any * // value set: * $filter = Horde_Ldap_Filter::create('sn', 'any'); * </code> * * @param string $attribute Name of the attribute the filter should apply * to. * @param string $match Matching rule (equals, begins, ends, contains, * greater, less, greaterOrEqual, lessOrEqual, * approx, any). * @param string $value If given, then this is used as a filter value. * @param boolean $escape Should $value be escaped? * * @return Horde_Ldap_Filter * @throws Horde_Ldap_Exception */ public static function create($attribute, $match, $value = '', $escape = true) { if ($escape) { $array = Horde_Ldap_Util::escapeFilterValue(array($value)); $value = $array[0]; } switch (Horde_String::lower($match)) { case 'equals': case '=': $filter = '(' . $attribute . '=' . $value . ')'; break; case 'begins': $filter = '(' . $attribute . '=' . $value . '*)'; break; case 'ends': $filter = '(' . $attribute . '=*' . $value . ')'; break; case 'contains': $filter = '(' . $attribute . '=*' . $value . '*)'; break; case 'greater': case '>': $filter = '(' . $attribute . '>' . $value . ')'; break; case 'less': case '<': $filter = '(' . $attribute . '<' . $value . ')'; break; case 'greaterorequal': case '>=': $filter = '(' . $attribute . '>=' . $value . ')'; break; case 'lessorequal': case '<=': $filter = '(' . $attribute . '<=' . $value . ')'; break; case 'approx': case '~=': $filter = '(' . $attribute . '~=' . $value . ')'; break; case 'any': case 'present': $filter = '(' . $attribute . '=*)'; break; default: throw new Horde_Ldap_Exception('Matching rule "' . $match . '" unknown'); } return new Horde_Ldap_Filter(array('filter' => $filter)); } /** * Combines two or more filter objects using a logical operator. * * Example: * <code> * $filter = Horde_Ldap_Filter::combine('or', array($filter1, $filter2)); * </code> * * If the array contains filter strings instead of filter objects, they * will be parsed. * * @param string $operator * The logical operator, either "and", "or", "not" or the logical * equivalents "&", "|", "!". * @param array|Horde_Ldap_Filter|string $filters * Array with Horde_Ldap_Filter objects and/or strings or a single * filter when using the "not" operator. * * @return Horde_Ldap_Filter * @throws Horde_Ldap_Exception */ public static function combine($operator, $filters) { // Substitute named operators with logical operators. switch ($operator) { case 'and': $operator = '&'; break; case 'or': $operator = '|'; break; case 'not': $operator = '!'; break; } // Tests for sane operation. switch ($operator) { case '!': // Not-combination, here we only accept one filter object or filter // string. if ($filters instanceof Horde_Ldap_Filter) { $filters = array($filters); // force array } elseif (is_string($filters)) { $filters = array(self::parse($filters)); } elseif (is_array($filters)) { throw new Horde_Ldap_Exception('Operator is "not" but $filter is an array'); } else { throw new Horde_Ldap_Exception('Operator is "not" but $filter is not a valid Horde_Ldap_Filter nor a filter string'); } break; case '&': case '|': if (!is_array($filters) || count($filters) < 2) { throw new Horde_Ldap_Exception('Parameter $filters is not an array or contains less than two Horde_Ldap_Filter objects'); } break; default: throw new Horde_Ldap_Exception('Logical operator is unknown'); } foreach ($filters as $key => $testfilter) { // Check for errors. if (is_string($testfilter)) { // String found, try to parse into an filter object. $filters[$key] = self::parse($testfilter); } elseif (!($testfilter instanceof Horde_Ldap_Filter)) { throw new Horde_Ldap_Exception('Invalid object passed in array $filters!'); } } return new Horde_Ldap_Filter(array('filters' => $filters, 'operator' => $operator)); } /** * Builds a filter (commonly for objectClass attributes) from different * configuration options. * * @param array $params Hash with configuration options that build the * search filter. Possible hash keys: * - 'filter': An LDAP filter string. * - 'objectclass' (string): An objectClass name. * - 'objectclass' (array): A list of objectClass * names. * @param string $operator How to combine mutliple 'objectclass' entries. * 'and' or 'or'. * * @return Horde_Ldap_Filter A filter matching the specified criteria. * @throws Horde_Ldap_Exception */ public static function build(array $params, $operator = 'and') { if (!empty($params['filter'])) { return self::parse($params['filter']); } if (!is_array($params['objectclass'])) { return self::create('objectclass', 'equals', $params['objectclass']); } $filters = array(); foreach ($params['objectclass'] as $objectclass) { $filters[] = self::create('objectclass', 'equals', $objectclass); } if (count($filters) == 1) { return $filters[0]; } return self::combine($operator, $filters); } /** * Parses a string into a Horde_Ldap_Filter object. * * @todo Leaf-mode: Do we need to escape at all? what about *-chars? Check * for the need of encoding values, tackle problems (see code comments). * * @param string $filter An LDAP filter string. * * @return Horde_Ldap_Filter * @throws Horde_Ldap_Exception */ public static function parse($filter) { if (!preg_match('/^\((.+?)\)$/', $filter, $matches)) { throw new Horde_Ldap_Exception('Invalid filter syntax, filter components must be enclosed in round brackets'); } if (in_array(substr($matches[1], 0, 1), array('!', '|', '&'))) { return self::_parseCombination($matches[1]); } else { return self::_parseLeaf($matches[1]); } } /** * Parses combined subfilter strings. * * Passes subfilters to parse() and combines the objects using the logical * operator detected. Each subfilter could be an arbitary complex * subfilter. * * @param string $filter An LDAP filter string. * * @return Horde_Ldap_Filter * @throws Horde_Ldap_Exception */ 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); } /** * Parses a single leaf component. * * @param string $filter An LDAP filter string. * * @return Horde_Ldap_Filter * @throws Horde_Ldap_Exception */ protected static function _parseLeaf($filter) { // Detect multiple leaf components. // [TODO] Maybe this will make problems with filters containing // brackets inside the value. if (strpos($filter, ')(')) { throw new Horde_Ldap_Exception('Invalid filter syntax: multiple leaf components detected'); } $filter_parts = preg_split('/(?<!\\\\)(=|=~|>|<|>=|<=)/', $filter, 2, PREG_SPLIT_DELIM_CAPTURE); if (count($filter_parts) != 3) { throw new Horde_Ldap_Exception('Invalid filter syntax: unknown matching rule used'); } // [TODO]: Do we need to escape at all? what about *-chars user provide // and that should remain special? I think, those prevent // escaping! We need to check against PERL Net::LDAP! // $value_arr = Horde_Ldap_Util::escapeFilterValue(array($filter_parts[2])); // $value = $value_arr[0]; return new Horde_Ldap_Filter(array('filter' => '(' . $filter_parts[0] . $filter_parts[1] . $filter_parts[2] . ')')); } /** * Returns the string representation of this filter. * * This method runs through all filter objects and creates the string * representation of the filter. * * @return string */ public function __toString() { if (!count($this->_filters)) { return $this->_filter; } $return = ''; foreach ($this->_filters as $filter) { $return .= (string)$filter; } return '(' . $this->_operator . $return . ')'; } }
Simpan