PageRenderTime 104ms CodeModel.GetById 20ms RepoModel.GetById 2ms app.codeStats 0ms

/libs/PEAR/Net/LDAP/Filter.php

https://bitbucket.org/tduarte/atmailopen
PHP | 320 lines | 122 code | 18 blank | 180 comment | 31 complexity | 326fc07dcf7d44638ea8f1b0948d2210 MD5 | raw file
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +--------------------------------------------------------------------------+
  4. // | Net_LDAP |
  5. // +--------------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2007 The PHP Group |
  7. // +--------------------------------------------------------------------------+
  8. // | This library is free software; you can redistribute it and/or |
  9. // | modify it under the terms of the GNU Lesser General Public |
  10. // | License as published by the Free Software Foundation; either |
  11. // | version 2.1 of the License, or (at your option) any later version. |
  12. // | |
  13. // | This library is distributed in the hope that it will be useful, |
  14. // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
  15. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
  16. // | Lesser General Public License for more details. |
  17. // | |
  18. // | You should have received a copy of the GNU Lesser General Public |
  19. // | License along with this library; if not, write to the Free Software |
  20. // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
  21. // +--------------------------------------------------------------------------+
  22. // | Authors: Benedikt Hallinger |
  23. // +--------------------------------------------------------------------------+
  24. //
  25. // $Id: Filter.php,v 1.7 2007/06/13 13:12:08 beni Exp $
  26. require_once("PEAR.php");
  27. require_once('Util.php');
  28. /**
  29. * Object representation of a part of a LDAP filter.
  30. *
  31. * This Class is not completely compatible to the PERL interface!
  32. *
  33. * The purpose of this class is, that users can easily build LDAP filters
  34. * without having to worry about right escaping etc.
  35. * A Filter is built using several independent filter objects
  36. * which are combined afterwards. This object works in two
  37. * modes, depending how the object is created.
  38. * If the object is created using the {@link create()} method, then this is a leaf-object.
  39. * If the object is created using the {@link combine()} method, then this is a container object.
  40. *
  41. * LDAP filters are defined in RFC-2254 and can be found under
  42. * {@link http://www.ietf.org/rfc/rfc2254.txt}
  43. *
  44. * Here a quick copy&paste example:
  45. * <code>
  46. * $filter0 = Net_LDAP_Filter::create('stars', 'equals', '***');
  47. * $filter_not0 = Net_LDAP_Filter::combine('not', $filter0);
  48. *
  49. * $filter1 = Net_LDAP_Filter::create('gn', 'begins', 'bar');
  50. * $filter2 = Net_LDAP_Filter::create('gn', 'ends', 'baz');
  51. * $filter_comp = Net_LDAP_Filter::combine('or',array($filter_not0, $filter1, $filter2));
  52. *
  53. * echo $filter_comp->asString();
  54. * // This will output: (|(!(stars=\0x5c0x2a\0x5c0x2a\0x5c0x2a))(gn=bar*)(gn=*baz))
  55. * // The stars in $filter0 are treaten as real stars unless you disable escaping.
  56. * </code>
  57. *
  58. * @package Net_LDAP
  59. * @author Benedikt Hallinger <beni@php.net>
  60. * @version $Revision: 1.7 $
  61. */
  62. class Net_LDAP_Filter extends PEAR
  63. {
  64. /**
  65. * Storage for combination of filters
  66. *
  67. * This variable holds a array of filter objects
  68. * that should be combined by this filter object.
  69. *
  70. * @access private
  71. * @var array
  72. */
  73. var $_subfilters = array();
  74. /**
  75. * Match of this filter
  76. *
  77. * If this is a leaf filter, then a matching rule is stored,
  78. * if it is a container, then it is a logical operator
  79. *
  80. * @access private
  81. * @var string
  82. */
  83. var $_match;
  84. /**
  85. * Single filter
  86. *
  87. * If we operate in leaf filter mode,
  88. * then the constructing method stores
  89. * the filter representation here
  90. *
  91. * @acces private
  92. * @var string
  93. */
  94. var $_filter;
  95. /**
  96. * Private, empty constructor
  97. *
  98. * Construction of Net_LDAP_Filter objects occours through either
  99. * {@link create()} or {@link combine()}
  100. *
  101. * @access private
  102. */
  103. function Net_LDAP_Filter()
  104. {
  105. }
  106. /**
  107. * Constructor of a new part of a LDAP filter.
  108. *
  109. * The following matching rules exists:
  110. * - equals: One of the attributes values is exactly $value
  111. * Please note that case sensitiviness is depends on the
  112. * attributes syntax configured in the server.
  113. * - begins: One of the attributes values must begin with $value
  114. * - ends: One of the attributes values must end with $value
  115. * - contains: One of the attributes values must contain $value
  116. * - any: The attribute can contain any value but must be existent
  117. * - greater: The attributes value is greater than $value
  118. * - less: The attributes value is less than $value
  119. * - greaterOrEqual: The attributes value is greater or equal than $value
  120. * - lessOrEqual: The attributes value is less or equal than $value
  121. * - approx: One of the attributes values is similar to $value
  122. *
  123. * If $escape is set to true (default) then $value will be escaped
  124. * properly. If it is set to false then $value will be treaten as raw value.
  125. *
  126. * Examples:
  127. * $filter = new Net_LDAP_Filter('sn', 'ends', 'foobar');
  128. * -> This will find entries that contain a attribute "sn" that ends with "foobar".
  129. * $filter = new Net_LDAP_Filter('sn', 'any');
  130. * -> This will find entries that contain a attribute "sn" that has any value set.
  131. *
  132. * @param string $attr_name Name of the attribute the filter should apply to
  133. * @param string $match Matching rule (equals, begins, ends, contains, greater, less, greaterOrEqual, lessOrEqual, approx, any)
  134. * @param string $value (optional) if given, then this is used as a filter
  135. * @param boolean $escape Should the whole $value be escaped? (default: yes, see {@link escape()} for detailed information)
  136. * @return Net_LDAP_Filter|Net_LDAP_Error
  137. * @see escape()
  138. * @todo implement greaterOrEqual, lessOrEqual, approx
  139. */
  140. function &create($attr_name, $match, $value = '', $escape = true)
  141. {
  142. $leaf_filter = new Net_LDAP_Filter();
  143. if ($escape) {
  144. $array = Net_LDAP_Util::escape_filter_value(array($value));
  145. $value = $array[0];
  146. }
  147. switch (strtolower($match)) {
  148. case 'equals':
  149. $leaf_filter->_filter = '(' . $attr_name . '=' . $value . ')';
  150. break;
  151. case 'begins':
  152. $leaf_filter->_filter = '(' . $attr_name . '=' . $value . '*)';
  153. break;
  154. case 'ends':
  155. $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . ')';
  156. break;
  157. case 'contains':
  158. $leaf_filter->_filter = '(' . $attr_name . '=*' . $value . '*)';
  159. break;
  160. case 'greater':
  161. $leaf_filter->_filter = '(' . $attr_name . '>' . $value . ')';
  162. break;
  163. case 'less':
  164. $leaf_filter->_filter = '(' . $attr_name . '<' . $value . ')';
  165. break;
  166. case 'greaterorequal':
  167. $leaf_filter->_filter = '(' . $attr_name . '>=' . $value . ')';
  168. break;
  169. case 'lessorequal':
  170. $leaf_filter->_filter = '(' . $attr_name . '<=' . $value . ')';
  171. break;
  172. case 'approx':
  173. $leaf_filter->_filter = '(' . $attr_name . '=~' . $value . ')';
  174. break;
  175. case 'any':
  176. $leaf_filter->_filter = '(' . $attr_name . '=*)';
  177. break;
  178. default:
  179. return PEAR::raiseError('Net_LDAP_Filter create error: matching rule "' . $match . '" not known!');
  180. }
  181. return $leaf_filter;
  182. }
  183. /**
  184. * Combine two or more filter objects using a logical operator
  185. *
  186. * This static method combines two or more filter objects and returns one single
  187. * filter object that contains all the others.
  188. * Call this method statically: $filter =& Net_LDAP_Filter('or', array($filter1, $filter2))
  189. *
  190. * @param string $log_op The locicall operator. May be "and", "or", "not" or the subsequent logical equivalents "&", "|", "!"
  191. * @param array|Net_LDAP_Filter $filters array with Net_LDAP_Filter objects
  192. * @return Net_LDAP_Filter|Net_LDAP_Error
  193. * @static
  194. */
  195. function &combine($log_op, $filters)
  196. {
  197. if (PEAR::isError($filters)) {
  198. return $filters;
  199. }
  200. // substitude named operators to logical operators
  201. if ($log_op == 'and') $log_op = '&';
  202. if ($log_op == 'or') $log_op = '|';
  203. if ($log_op == 'not') $log_op = '!';
  204. // tests for sane operation
  205. if ($log_op == '!') {
  206. // Not-combination, here we also accept one filter object
  207. if (!is_array($filters) && is_a($filters, 'Net_LDAP_Filter')) {
  208. $filters = array($filters); // force array
  209. } else {
  210. $err = PEAR::raiseError('Net_LDAP_Filter combine error: operator is "not" but $filter is not a valid Net_LDAP_Filter nor an array!');
  211. return $err;
  212. }
  213. } elseif ($log_op == '&' || $log_op == '|') {
  214. if (!is_array($filters) || count($filters) < 2) {
  215. $err = PEAR::raiseError('Net_LDAP_Filter combine error: Parameter $filters is not a array or contains less than two Net_LDAP_Filter objects!');
  216. return $err;
  217. }
  218. } else {
  219. $err = PEAR::raiseError('Net_LDAP_Filter combine error: logical operator is not known!');
  220. return $err;
  221. }
  222. if ($log_op != '&' && $log_op != '|' && $log_op != '!') {
  223. return PEAR::raiseError('Net_LDAP_Filter combine error: Logical operator "' . $log_op . '" not known!');
  224. }
  225. $combined_filter = new Net_LDAP_Filter();
  226. foreach ($filters as $testfilter) { // check for errors
  227. if (is_a($testfilter, 'Net_LDAP_Error')) {
  228. return $testfilter;
  229. }
  230. }
  231. $combined_filter->_subfilters = $filters;
  232. $combined_filter->_match = $log_op;
  233. return $combined_filter;
  234. }
  235. /**
  236. * Get the string representation of this filter
  237. *
  238. * This method runs through all filter objects and creates
  239. * the string representation of the filter. If this
  240. * filter object is a leaf filter, then it will return
  241. * the string representation of this filter.
  242. *
  243. * @return string
  244. */
  245. function asString()
  246. {
  247. if ($this->_isLeaf()) {
  248. $return = $this->_filter;
  249. } else {
  250. $return = '';
  251. foreach ($this->_subfilters as $filter) {
  252. $return = $return.$filter->asString();
  253. }
  254. $return = '(' . $this->_match . $return . ')';
  255. }
  256. return $return;
  257. }
  258. /**
  259. * Alias for perl interface as_string()
  260. *
  261. * @see asString()
  262. */
  263. function as_string()
  264. {
  265. return $this->asString();
  266. }
  267. /**
  268. * This can be used to escape a string to provide a valid LDAP-Filter.
  269. *
  270. * LDAP will only recognise certain characters as the
  271. * character istself if it is properly escaped. This is
  272. * what this method does.
  273. * The method can be called statically, so you can use it outside
  274. * for your own purposes (eg for escaping only parts of strings)
  275. *
  276. * In fact, this is just a shorthand to {@link Net_LDAP_Util::escape_filter_value()}.
  277. *
  278. * @static
  279. * @param string $string Any string who should be escaped
  280. * @return string The string $string, but escaped
  281. * @deprecated Do not use this method anymore, instead use Net_LDAP_Util::escape_filter_value()
  282. */
  283. function escape($string)
  284. {
  285. return PEAR::raiseError("PLEASE DO NOT USE Net_LDAP_Filter anymore! use Net_LDAP_Util::escape_filter_value() instead!");
  286. }
  287. /**
  288. * Is this a container or a leaf filter object?
  289. *
  290. * @access private
  291. * @return boolean
  292. */
  293. function _isLeaf()
  294. {
  295. if (count($this->_subfilters) > 0) {
  296. return false; // Container!
  297. } else {
  298. return true; // Leaf!
  299. }
  300. }
  301. }
  302. ?>