PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/horde-3.3.13/lib/Horde/Group/kolab.php

#
PHP | 499 lines | 264 code | 61 blank | 174 comment | 43 complexity | f2c7444759f2e9546b9add1727833e9c MD5 | raw file
Possible License(s): LGPL-2.0
  1. <?php
  2. require_once 'Horde/Group/ldap.php';
  3. require_once 'Horde/LDAP.php';
  4. /**
  5. * The Group_kolab class provides a Kolab backend for the Horde groups
  6. * system.
  7. *
  8. * FIXME: A better solution would be to let this class rely on
  9. * Horde/Kolab/LDAP.php.
  10. *
  11. * $Horde: framework/Group/Group/kolab.php,v 1.4.2.2 2009/01/06 15:23:08 jan Exp $
  12. *
  13. * Copyright 2005-2009 The Horde Project (http://www.horde.org/)
  14. *
  15. * See the enclosed file COPYING for license information (LGPL). If you
  16. * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  17. *
  18. * @author Gunnar Wrobel <wrobel@pardus.de>
  19. * @since Horde 3.2
  20. * @package Horde_Group
  21. */
  22. class Group_kolab extends Group_ldap {
  23. /**
  24. * A marker for fatal errors
  25. */
  26. var $_error;
  27. /**
  28. * Constructor.
  29. */
  30. function Group_kolab($params)
  31. {
  32. if (!function_exists('ldap_connect')) {
  33. $this->_error = PEAR::raiseError(_("The Kolab group driver requires LDAP support."));
  34. }
  35. $this->_params = array();
  36. $this->_params['hostspec'] = $GLOBALS['conf']['kolab']['ldap']['server'];
  37. $this->_params['basedn'] = $GLOBALS['conf']['kolab']['ldap']['basedn'];
  38. $this->_params['binddn'] = $GLOBALS['conf']['kolab']['ldap']['phpdn'];
  39. $this->_params['password'] = $GLOBALS['conf']['kolab']['ldap']['phppw'];
  40. $this->_params['version'] = 3;
  41. $this->_params['gid'] = 'cn';
  42. $this->_params['memberuid'] = 'member';
  43. $this->_params['attrisdn'] = true;
  44. $this->_params['filter_type'] = 'objectclass';
  45. $this->_params['objectclass'] = 'kolabGroupOfNames';
  46. $this->_params['newgroup_objectclass'] = 'kolabGroupOfNames';
  47. $this->_filter = 'objectclass=' . $this->_params['objectclass'];
  48. $this->__wakeup();
  49. }
  50. /**
  51. * Initializes the object.
  52. */
  53. function __wakeup()
  54. {
  55. foreach (array_keys($this->_groupCache) as $name) {
  56. $this->_groupCache[$name]->setGroupOb($this);
  57. }
  58. }
  59. /**
  60. * Returns the properties that need to be serialized.
  61. *
  62. * @return array List of serializable properties.
  63. */
  64. function __sleep()
  65. {
  66. $properties = get_object_vars($this);
  67. unset($properties['_datatree'], $properties['_ds']);
  68. $properties = array_keys($properties);
  69. return $properties;
  70. }
  71. /**
  72. * Returns a new group object.
  73. *
  74. * @param string $name The group's name.
  75. * @param string $parent The group's parent's name.
  76. *
  77. * @return Kolab_Group A new group object.
  78. */
  79. function &newGroup($name)
  80. {
  81. return PEAR::raiseError(_("Unsupported"));
  82. }
  83. /**
  84. * Adds a group to the groups system. The group must first be created with
  85. * Group::newGroup(), and have any initial users added to it, before this
  86. * function is called.
  87. *
  88. * @param Kolab_Group $group The new group object.
  89. */
  90. function addGroup($group)
  91. {
  92. return PEAR::raiseError(_("Unsupported"));
  93. }
  94. /**
  95. * Stores updated data - users, etc. - of a group to the backend system.
  96. *
  97. * @param Kolab_Group $group The group to update.
  98. */
  99. function updateGroup($group)
  100. {
  101. return PEAR::raiseError(_("Unsupported"));
  102. }
  103. /**
  104. * Removes a group from the groups system permanently.
  105. *
  106. * @param Kolab_Group $group The group to remove.
  107. * @param boolean $force Force to remove every child.
  108. */
  109. function removeGroup($group, $force = false)
  110. {
  111. return PEAR::raiseError(_("Unsupported"));
  112. }
  113. /**
  114. * Return a Kolab_Group object corresponding to the given dn, with the
  115. * users and other data retrieved appropriately.
  116. *
  117. * @param string $dn The dn of the group to retrieve.
  118. *
  119. * @return Kolab_Group The requested group.
  120. */
  121. function &getGroupById($dn)
  122. {
  123. static $cache = array();
  124. if (!isset($cache[$dn])) {
  125. if (is_a($this->_error, 'PEAR_Error')) {
  126. return $this->_error;
  127. }
  128. /* Connect to the LDAP server. */
  129. $success = $this->_connect();
  130. if (is_a($success, 'PEAR_Error')) {
  131. return PEAR::raiseError($success->getMessage());
  132. }
  133. $search = @ldap_search($this->_ds, $dn, $this->_filter);
  134. if (!$search) {
  135. return PEAR::raiseError(_("Could not reach the LDAP server"));
  136. }
  137. $result = @ldap_get_entries($this->_ds, $search);
  138. @ldap_close($this->_ds);
  139. if (!is_array($result) || (count($result) <= 1)) {
  140. return PEAR::raiseError(_("Empty result"));
  141. }
  142. $attributes = array();
  143. for ($i = 0; $i < $result[0]['count']; $i++) {
  144. if ($result[0][$result[0][$i]]['count'] > 1) {
  145. $attributes[$result[0][$i]] = array();
  146. for ($j = 0; $j < $result[0][$result[0][$i]]['count']; $j++) {
  147. $attributes[$result[0][$i]][] = $result[0][$result[0][$i]][$j];
  148. }
  149. } else {
  150. $attributes[$result[0][$i]] = $result[0][$result[0][$i]][0];
  151. }
  152. }
  153. $attributes['dn'] = $result[0]['dn'];
  154. $group = new Kolab_Group($this->getGroupName($dn));
  155. $group->_fromAttributes($attributes);
  156. $group->setGroupOb($this);
  157. $cache[$dn] = $group;
  158. }
  159. return $cache[$dn];
  160. }
  161. /**
  162. * Retrieve the ID of the given group.
  163. *
  164. * NOTE: If given a group name, this function can be unreliable if more
  165. * than one group exists with the same name.
  166. *
  167. * @param mixed $group LDAP_Group object, or a group name (string)
  168. *
  169. * @return string The group's ID.
  170. */
  171. function getGroupId($group)
  172. {
  173. static $cache = array();
  174. if (is_a($group, 'Kolab_Group')) {
  175. return $group->getDn();
  176. }
  177. if (!isset($cache[$group])) {
  178. if (is_a($this->_error, 'PEAR_Error')) {
  179. return $this->_error;
  180. }
  181. $this->_connect();
  182. $search = @ldap_search($this->_ds, $this->_params['basedn'],
  183. $this->_params['gid'] . '=' . $group,
  184. array($this->_params['gid']));
  185. if (!$search) {
  186. return PEAR::raiseError(_("Could not reach the LDAP server"));
  187. }
  188. $result = @ldap_get_entries($this->_ds, $search);
  189. @ldap_close($this->_ds);
  190. if (!is_array($result) || (count($result) <= 1)) {
  191. return PEAR::raiseError(_("Empty result"));
  192. }
  193. $cache[$group] = $result[0]['dn'];
  194. }
  195. return $cache[$group];
  196. }
  197. /**
  198. * Get a list of the parents of a child group.
  199. *
  200. * @param string $dn The fully qualified group dn
  201. *
  202. * @return array Nested array of parents
  203. */
  204. function getGroupParents($dn)
  205. {
  206. return array();
  207. }
  208. /**
  209. * Get the parent of the given group.
  210. *
  211. * @param string $dn The dn of the child group.
  212. *
  213. * @return string The dn of the parent group.
  214. */
  215. function getGroupParent($dn)
  216. {
  217. return null;
  218. }
  219. /**
  220. * Get a list of parents all the way up to the root object for the given
  221. * group.
  222. *
  223. * @param string $dn The dn of the group.
  224. *
  225. * @return array A flat list of all of the parents of the given group,
  226. * hashed in $dn => $name format.
  227. */
  228. function getGroupParentList($dn)
  229. {
  230. return array();
  231. }
  232. /**
  233. * Tries to find a DN for a given kolab mail address.
  234. *
  235. * @param string $mail The mail address to search for.
  236. *
  237. * @return string The corresponding dn or false.
  238. */
  239. function dnForMail($mail)
  240. {
  241. $filter = '(&(objectclass=kolabInetOrgPerson)(mail=' . Horde_LDAP::quote($mail) . '))';
  242. $search = @ldap_search($this->_ds, $this->_params['basedn'], $filter);
  243. if (!$search) {
  244. return PEAR::raiseError(_("Could not reach the LDAP server"));
  245. }
  246. $dn = @ldap_first_entry($this->_ds, $search);
  247. if ($dn) {
  248. return ldap_get_dn($this->_ds, $dn);
  249. }
  250. return PEAR::raiseError(sprintf(_("Error searching for user with the email address \"%s\"!"),
  251. $mail));
  252. }
  253. /**
  254. * Get a list of every group that the given user is a member of.
  255. *
  256. * @param string $user The user to get groups for.
  257. * @param boolean $parentGroups Also return the parents of any groups?
  258. *
  259. * @return array An array of all groups the user is in.
  260. */
  261. function getGroupMemberships($user, $parentGroups = false)
  262. {
  263. static $cache = array();
  264. if (empty($cache[$user])) {
  265. if (is_a($this->_error, 'PEAR_Error')) {
  266. return $this->_error;
  267. }
  268. /* Connect to the LDAP server. */
  269. $success = $this->_connect();
  270. if (is_a($success, 'PEAR_Error')) {
  271. return PEAR::raiseError($success->getMessage());
  272. }
  273. $dn = $this->dnForMail($user);
  274. if (is_a($dn, 'PEAR_Error')) {
  275. return $dn;
  276. }
  277. // Set up search filter
  278. $filter = '(' . $this->_params['memberuid'] . '=' . $dn . ')';
  279. // Perform search
  280. $search = @ldap_search($this->_ds, $this->_params['basedn'], $filter);
  281. if (!$search) {
  282. return PEAR::raiseError(_("Could not reach the LDAP server"));
  283. }
  284. $result = @ldap_get_entries($this->_ds, $search);
  285. @ldap_close($this->_ds);
  286. if (!is_array($result) || (count($result) <= 1)) {
  287. return array();
  288. }
  289. $groups = array();
  290. $current_charset = NLS::getCharset();
  291. for ($i = 0; $i < $result['count']; $i++) {
  292. $utf8_dn = String::convertCharset($result[$i]['dn'], 'UTF-8', $current_charset);
  293. $groups[$utf8_dn] = $this->getGroupName($utf8_dn);
  294. }
  295. $cache[$user] = $groups;
  296. }
  297. return $cache[$user];
  298. }
  299. }
  300. /**
  301. *
  302. *
  303. * @author Ben Chavet <ben@horde.org>
  304. * @since Horde 3.1
  305. * @package Horde_Group
  306. */
  307. class Kolab_Group extends LDAP_Group {
  308. /**
  309. * Constructor.
  310. *
  311. * @param string $name The name of this group.
  312. * @param string $parent The dn of the parent of this group.
  313. */
  314. function Kolab_Group($name, $parent = null)
  315. {
  316. $this->setName($name);
  317. }
  318. /**
  319. * Fetch the ID of this group
  320. *
  321. * @return string The group's ID
  322. */
  323. function getId()
  324. {
  325. return $this->getDn();
  326. }
  327. /**
  328. * Save any changes to this object to the backend permanently.
  329. */
  330. function save()
  331. {
  332. return PEAR::raiseError(_("Unsupported"));
  333. }
  334. /**
  335. * Adds a user to this group, and makes sure that the backend is
  336. * updated as well.
  337. *
  338. * @param string $username The user to add.
  339. */
  340. function addUser($username, $update = true)
  341. {
  342. return PEAR::raiseError(_("Unsupported"));
  343. }
  344. /**
  345. * Removes a user from this group, and makes sure that the backend
  346. * is updated as well.
  347. *
  348. * @param string $username The user to remove.
  349. */
  350. function removeUser($username, $update = true)
  351. {
  352. return PEAR::raiseError(_("Unsupported"));
  353. }
  354. /**
  355. * Get all the users recently added or removed from the group.
  356. */
  357. function getAuditLog()
  358. {
  359. return array();
  360. }
  361. /**
  362. * Clears the audit log. To be called after group update.
  363. */
  364. function clearAuditLog()
  365. {
  366. }
  367. /**
  368. * Sets the name of this object.
  369. *
  370. * @param string $name The name to set this object's name to.
  371. */
  372. function getDn()
  373. {
  374. return $this->name . ',' . $GLOBALS['conf']['kolab']['ldap']['basedn'];
  375. }
  376. /**
  377. * Take in a list of attributes from the backend and map it to our
  378. * internal data array.
  379. *
  380. * @param array $attributes The list of attributes from the backend.
  381. */
  382. function _fromAttributes($attributes = array())
  383. {
  384. $this->data['users'] = array();
  385. foreach ($attributes as $key => $value) {
  386. if (String::lower($key) == 'member') {
  387. if (is_array($value)) {
  388. foreach ($value as $user) {
  389. $pattern = '/^cn=([^,]+).*$/';
  390. $results = array();
  391. preg_match($pattern, $user, $results);
  392. if (isset($results[1])) {
  393. $user = $results[1];
  394. }
  395. $this->data['users'][$user] = '1';
  396. }
  397. } else {
  398. $pattern = '/^cn=([^,]+).*$/';
  399. $results = array();
  400. preg_match($pattern, $value, $results);
  401. if (isset($results[1])) {
  402. $value = $results[1];
  403. }
  404. $this->data['users'][$value] = '1';
  405. }
  406. } elseif ($key == 'mail') {
  407. $this->data['email'] = $value;
  408. } else {
  409. $this->data[$key] = $value;
  410. }
  411. }
  412. }
  413. /**
  414. * Map this object's attributes from the data array into a format that
  415. * can be stored in an LDAP entry.
  416. *
  417. * @return array The entry array.
  418. */
  419. function _toAttributes()
  420. {
  421. $attributes = array();
  422. foreach ($this->data as $key => $value) {
  423. if ($key == 'users') {
  424. foreach ($value as $user => $membership) {
  425. $user = 'cn=' . $user . ',' . $GLOBALS['conf']['kolab']['ldap']['basedn'];
  426. $attributes['member'][] = $user;
  427. }
  428. } elseif ($key == 'email') {
  429. if (!empty($value)) {
  430. $attributes['mail'] = $value;
  431. }
  432. } elseif ($key != 'dn' && $key != 'member') {
  433. $attributes[$key] = !empty($value) ? $value : ' ';
  434. }
  435. }
  436. return $attributes;
  437. }
  438. }