1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
16: class Horde_Group_Ldap extends Horde_Group_Base
17: {
18: 19: 20: 21: 22:
23: protected $_ldap;
24:
25: 26: 27: 28: 29:
30: protected $_params;
31:
32: 33: 34: 35: 36:
37: protected $_filter;
38:
39: 40: 41: 42: 43:
44: public function __construct($params)
45: {
46: $params = array_merge(
47: array('binddn' => '',
48: 'bindpw' => '',
49: 'gid' => 'cn',
50: 'memberuid' => 'memberUid',
51: 'objectclass' => array('posixGroup'),
52: 'newgroup_objectclass' => array('posixGroup')),
53: $params
54: );
55:
56:
57: foreach (array('ldap', 'basedn') as $param) {
58: if (!isset($params[$param])) {
59: throw new Horde_Group_Exception('The \'' . $param . '\' parameter is missing.');
60: }
61: }
62:
63:
64: $this->_ldap = $params['ldap'];
65: unset($params['ldap']);
66:
67:
68: $params['gid'] = Horde_String::lower($params['gid']);
69: $params['memberuid'] = Horde_String::lower($params['memberuid']);
70: if (!is_array($params['newgroup_objectclass'])) {
71: $params['newgroup_objectclass'] = array($params['newgroup_objectclass']);
72: }
73: foreach ($params['newgroup_objectclass'] as &$objectClass) {
74: $objectClass = Horde_String::lower($objectClass);
75: }
76:
77:
78: try {
79: $this->_filter = Horde_Ldap_Filter::build($params['search']);
80: } catch (Horde_Ldap_Exception $e) {
81: throw new Horde_Group_Exception($e);
82: }
83:
84: $this->_params = $params;
85: }
86:
87: 88: 89: 90: 91:
92: public function readOnly()
93: {
94: return !isset($this->_params['writedn']) ||
95: !isset($this->_params['writepw']);
96: }
97:
98: 99: 100: 101: 102:
103: public function renameSupported()
104: {
105: return false;
106: }
107:
108: 109: 110: 111: 112: 113: 114: 115: 116:
117: public function create($name, $email = null)
118: {
119: if ($this->readOnly()) {
120: throw new Horde_Group_Exception('This group backend is read-only.');
121: }
122:
123: $attributes = array(
124: $this->_params['gid'] => $name,
125: 'objectclass' => $this->_params['newgroup_objectclass'],
126: 'gidnumber' => $this->_nextGid());
127: if (!empty($email)) {
128: $attributes['mail'] = $email;
129: }
130:
131: return $this->_create($name, $attributes);
132: }
133:
134: 135: 136: 137: 138: 139: 140: 141: 142:
143: protected function _create($name, array $attributes)
144: {
145: $dn = Horde_Ldap::quoteDN(array(array($this->_params['gid'], $name))) . ',' . $this->_params['basedn'];
146: try {
147: $entry = Horde_Ldap_Entry::createFresh($dn, $attributes);
148: $this->_rebind(true);
149: $this->_ldap->add($entry);
150: $this->_rebind(false);
151: return $dn;
152: } catch (Horde_Ldap_Exception $e) {
153: throw new Horde_Group_Exception($e);
154: }
155: }
156:
157: 158: 159: 160: 161: 162: 163: 164:
165: public function rename($gid, $name)
166: {
167: throw new Horde_Group_Exception('Renaming groups is not supported with the LDAP driver.');
168: }
169:
170: 171: 172: 173: 174: 175: 176:
177: public function remove($gid)
178: {
179: if ($this->readOnly()) {
180: throw new Horde_Group_Exception('This group backend is read-only.');
181: }
182:
183: try {
184: $this->_rebind(true);
185: $this->_ldap->delete($gid);
186: $this->_rebind(false);
187: } catch (Horde_Ldap_Exception $e) {
188: throw new Horde_Group_Exception($e);
189: }
190: }
191:
192: 193: 194: 195: 196: 197: 198: 199:
200: public function exists($gid)
201: {
202: try {
203: return $this->_ldap->exists($gid);
204: } catch (Horde_Ldap_Exception $e) {
205: throw new Horde_Group_Exception($e);
206: }
207: }
208:
209: 210: 211: 212: 213: 214: 215: 216: 217:
218: public function getName($gid)
219: {
220: try {
221: $entry = $this->_ldap->getEntry($gid);
222: return $entry->getValue($this->_params['gid'], 'single');
223: } catch (Horde_Ldap_Exception $e) {
224: throw new Horde_Group_Exception($e);
225: }
226: }
227:
228: 229: 230: 231: 232: 233: 234: 235: 236:
237: public function getData($gid)
238: {
239: try {
240: $entry = $this->_ldap->getEntry($gid);
241: $attributes = $entry->getValues();
242: } catch (Horde_Ldap_Exception $e) {
243: throw new Horde_Group_Exception($e);
244: }
245: $data = array();
246: foreach ($attributes as $attribute => $value) {
247: switch ($attribute) {
248: case $this->_params['gid']:
249: $attribute = 'name';
250: break;
251: case 'mail':
252: $attribute = 'email';
253: break;
254: }
255: $data[$attribute] = $value;
256: }
257: return $data;
258: }
259:
260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271:
272: public function setData($gid, $attribute, $value = null)
273: {
274: if ($this->readOnly()) {
275: throw new Horde_Group_Exception('This group backend is read-only.');
276: }
277:
278: $attributes = is_array($attribute)
279: ? $attribute
280: : array($attribute => $value);
281: try {
282: $entry = $this->_ldap->getEntry($gid);
283: foreach ($attributes as $attribute => $value) {
284: switch ($attribute) {
285: case 'name':
286: $attribute = $this->_params['gid'];
287: break;
288: case 'email':
289: $attribute = 'mail';
290: break;
291: }
292: $entry->replace(array($attribute => $value));
293: }
294: $this->_rebind(true);
295: $entry->update();
296: $this->_rebind(false);
297: } catch (Horde_Ldap_Exception $e) {
298: throw new Horde_Group_Exception($e);
299: }
300: }
301:
302: 303: 304: 305: 306: 307: 308: 309: 310:
311: public function listAll($member = null)
312: {
313: if (!is_null($member)) {
314: return $this->listGroups($member);
315: }
316:
317: $attr = $this->_params['gid'];
318: try {
319: $search = $this->_ldap->search($this->_params['basedn'],
320: $this->_filter,
321: array($attr));
322: } catch (Horde_Ldap_Exception $e) {
323: throw new Horde_Group_Exception($e);
324: }
325:
326: $entries = array();
327: foreach ($search->sortedAsArray(array($attr)) as $entry) {
328: $entries[$entry['dn']] = $entry[$attr][0];
329: }
330: return $entries;
331: }
332:
333: 334: 335: 336: 337: 338: 339: 340: 341:
342: public function listUsers($gid)
343: {
344: $attr = $this->_params['memberuid'];
345: try {
346: $entry = $this->_ldap->getEntry($gid, array($attr));
347: if (!$entry->exists($attr)) {
348: return array();
349: }
350:
351: if (empty($this->_params['attrisdn'])) {
352: return $entry->getValue($attr, 'all');
353: }
354:
355: $users = array();
356: foreach ($entry->getValue($attr, 'all') as $user) {
357: $dn = Horde_Ldap_Util::explodeDN($user,
358: array('onlyvalues' => true));
359:
360:
361: $user = $dn[0];
362:
363: if (is_array($element)) {
364: $user = $element[0];
365: }
366: $users[] = $user;
367: }
368: return $users;
369: } catch (Horde_Ldap_Exception $e) {
370: throw new Horde_Group_Exception($e);
371: }
372: }
373:
374: 375: 376: 377: 378: 379: 380: 381:
382: public function listGroups($user)
383: {
384: $attr = $this->_params['gid'];
385: try {
386: if (!empty($this->_params['attrisdn'])) {
387: $user = $this->_ldap->findUserDN($user);
388: }
389: $filter = Horde_Ldap_Filter::create($this->_params['memberuid'],
390: 'equals', $user);
391: $filter = Horde_Ldap_Filter::combine('and', array($this->_filter, $filter));
392: $search = $this->_ldap->search($this->_params['basedn'], $filter,
393: array($attr));
394: } catch (Horde_Ldap_Exception $e) {
395: throw new Horde_Group_Exception($e);
396: }
397: $entries = array();
398: foreach ($search->sortedAsArray(array($attr)) as $entry) {
399: $entries[$entry['dn']] = $entry[$attr][0];
400: }
401: return $entries;
402: }
403:
404: 405: 406: 407: 408: 409: 410: 411: 412:
413: public function addUser($gid, $user)
414: {
415: if ($this->readOnly()) {
416: throw new Horde_Group_Exception('This group backend is read-only.');
417: }
418:
419: $attr = $this->_params['memberuid'];
420: try {
421: if (!empty($this->_params['attrisdn'])) {
422: $user = $this->_ldap->findUserDN($user);
423: }
424: $entry = $this->_ldap->getEntry($gid, array($attr));
425: $entry->add(array($attr => $user));
426: $this->_rebind(true);
427: $entry->update();
428: $this->_rebind(false);
429: } catch (Horde_Ldap_Exception $e) {
430: throw new Horde_Group_Exception($e);
431: }
432: }
433:
434: 435: 436: 437: 438: 439: 440: 441: 442:
443: public function removeUser($gid, $user)
444: {
445: $attr = $this->_params['memberuid'];
446: try {
447: if (!empty($this->_params['attrisdn'])) {
448: $user = $this->_ldap->findUserDN($user);
449: }
450: $entry = $this->_ldap->getEntry($gid, array($attr));
451: $entry->delete(array($attr => $user));
452: $this->_rebind(true);
453: $entry->update();
454: $this->_rebind(false);
455: } catch (Horde_Ldap_Exception $e) {
456: throw new Horde_Group_Exception($e);
457: }
458: }
459:
460: 461: 462: 463: 464: 465: 466: 467: 468:
469: public function search($name)
470: {
471: $attr = $this->_params['gid'];
472: try {
473: $result = $this->_ldap->search(
474: $this->_params['basedn'],
475: Horde_Ldap_Filter::create($attr, 'contains', $name),
476: array($attr));
477: } catch (Horde_Ldap_Exception $e) {
478: throw new Horde_Group_Exception($e);
479: }
480: $entries = array();
481: foreach ($result->sortedAsArray(array($attr)) as $entry) {
482: $entries[$entry['dn']] = $entry[$attr][0];
483: }
484: return $entries;
485: }
486:
487: 488: 489: 490: 491: 492: 493: 494:
495: protected function _nextGid()
496: {
497: try {
498: $search = $this->_ldap->search(
499: $this->_params['basedn'],
500: $this->_filter,
501: array('attributes' => array('gidnumber')));
502: } catch (Horde_Ldap_Exception $e) {
503: throw new Horde_Group_Exception($e);
504: }
505:
506: if (!$search->count()) {
507: return 1;
508: }
509:
510: $nextgid = 0;
511: foreach ($search as $entry) {
512: $nextgid = max($nextgid, $entry->getValue('gidnumber', 'single'));
513: }
514:
515: return $nextgid + 1;
516: }
517:
518: 519: 520: 521: 522: 523: 524: 525:
526: protected function _rebind($write)
527: {
528: if ($write) {
529: $this->_ldap->bind($this->_params['writedn'], $this->_params['writepw']);
530: } else {
531: $this->_ldap->bind();
532: }
533: }
534: }
535: