1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13: class Vilma_Driver_Qmailldap extends Vilma_Driver_Sql
14: {
15: 16: 17: 18: 19:
20: protected $_ldap;
21:
22: 23: 24: 25: 26:
27: protected $_users = array();
28:
29: 30: 31: 32: 33:
34: protected $_fieldmap = array(
35: 'address' => 'mail',
36: 'user_name' => 'uid',
37: 'user_crypt' => 'userpassword',
38: 'user_full_name' => 'cn',
39: 'user_uid' => 'qmailuid',
40: 'user_gid' => 'qmailgid',
41: 'user_home_dir' => 'homedirectory',
42: 'user_mail_dir' => 'mailmessagestore',
43: 'user_mail_quota_bytes' => 'mailquotasize',
44: 'user_mail_quota_count' => 'mailquotacount',
45: 'user_enabled' => 'accountstatus',
46: );
47:
48: 49: 50: 51: 52:
53: public function __construct($params)
54: {
55: $params = array_merge(
56: Horde::getDriverConfig('storage', 'sql'),
57: $params);
58: parent::__construct($params);
59: $this->_connect();
60: }
61:
62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72:
73: protected function _deleteDomain($domain_id)
74: {
75: $domain_record = $this->getDomain($domain_id);
76: $domain_name = $domain_record['domain_name'];
77:
78:
79: $sql = 'DELETE FROM vilma_domains WHERE domain_id=?';
80: $values = array((int)$domain_id);
81:
82: Horde::logMessage($sql, 'DEBUG');
83: return $this->_db->query($sql, $values);
84: }
85:
86: 87: 88: 89: 90: 91: 92: 93:
94: public function getDomainNumUsers($domain_name)
95: {
96: return count($this->_getUsers($domain_name));
97: }
98:
99: 100: 101: 102: 103: 104: 105: 106: 107: 108:
109: public function getUsers($domain = null)
110: {
111:
112: if (is_null($domain) && isset($this->_users['_all'])) {
113: return $this->_users['_all'];
114: }
115:
116: if (!is_null($domain) && isset($this->_users[$domain])) {
117: return $this->_users[$domain];
118: }
119:
120: $filter = '(&';
121: if (!is_null($domain)) {
122: $filter .= '(mail=*@' . $domain . ')';
123: } else {
124: $domain = '_all';
125: }
126:
127:
128: $filter .= '(!(mailForwardingAddress=*))';
129:
130:
131: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
132: $filter .= '(objectClass=' . $objectclass . ')';
133: }
134: $filter .= ')';
135:
136: Horde::logMessage($filter, 'DEBUG');
137: $res = ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
138: if ($res === false) {
139: throw new Vilma_Exception(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
140: }
141:
142: $res = ldap_get_entries($this->_ldap, $res);
143: if ($res === false) {
144: throw new Vilma_Exception(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
145: }
146:
147: $this->_users[$domain] = array();
148:
149: for ($i = 0; isset($res[$id]); $user = $res[$i++]) {
150: $info = array(
151: 'id' => $user['dn'],
152: 'address' => $user[$this->_fieldmap['address']][0],
153: 'type' => 'user',
154: 'user_name' => $user[$this->_fieldmap['user_name']][0]);
155:
156:
157:
158: if (isset($user[$this->_fieldmap['user_crypt']])) {
159: $info['user_crypt'] = $user[$this->_fieldmap['user_crypt']][0];
160: } else {
161: $info['user_crypt'] = '';
162: }
163: $info['user_full_name'] = $user[$this->_fieldmap['user_full_name']][0];
164:
165:
166: $info['user_uid'] = @$user[$this->_fieldmap['user_uid']][0];
167: $info['user_gid'] = @$user[$this->_fieldmap['user_gid']][0];
168: $info['user_home_dir'] = @$user[$this->_fieldmap['user_home_dir']][0];
169: $info['user_mail_dir'] = @$user[$this->_fieldmap['user_mail_dir']][0];
170: $info['user_mail_quota_bytes'] = @$user[$this->_fieldmap['user_mail_quota_bytes']][0];
171: $info['user_mail_quota_count'] = @$user[$this->_fieldmap['user_mail_quota_count']][0];
172:
173:
174: if (!isset($user[$this->_fieldmap['user_enabled']][0]) ||
175: $user[$this->_fieldmap['user_enabled']][0] == 'active') {
176: $info['user_enabled'] = 'active';
177: } else {
178:
179:
180:
181:
182: $info['user_enabled'] = $user[$this->_fieldmap['user_enabled']][0];
183: }
184:
185: $this->_users[$domain][$i] = $info;
186: }
187:
188: return $this->_users[$domain];
189: }
190:
191: 192: 193: 194: 195: 196: 197: 198:
199: public function getUser($user_id)
200: {
201: $user = $this->getUserStatus($user_id);
202: if (is_array($user)) {
203: return $user;
204: }
205: throw new Vilma_Exception(_("Unable to qualify address."));
206: }
207:
208: 209: 210: 211: 212: 213: 214: 215:
216: protected function _saveUser($info)
217: {
218: switch ($info['mode']) {
219: case 'edit':
220: return $this->_updateUser($info);
221: case 'new':
222: return $this->_createUser($info);
223: }
224:
225: throw new Vilma_Exception(_("Unable to save user information."));
226: }
227:
228: 229: 230: 231: 232: 233: 234: 235:
236: protected function _updateUser($info)
237: {
238: $address = $info['address'];
239: if (empty($address)) {
240: $user_name = $info['user_name'];
241: $domain = $info['domain'];
242: if (empty($user_name)) {
243: throw new Vilma_Exception(_("Unable to acquire handle on address."));
244: }
245: $address = $info['user_name'] . $info['domain'];
246: }
247: $addrinfo = $this->getAddressInfo($address);
248: $type = $addrinfo['type'];
249: if ($type != 'user') {
250: throw new Vilma_Exception(sprintf(_("Unable to save account of type \"%s\""), $type));
251: }
252:
253: $user_info = $this->_searchForUser($address);
254: if ($res['count'] === 0) {
255: throw new Vilma_Exception(_("Error reading address information from backend."));
256: }
257:
258: $objectClassData = null;
259: if (isset($user_info[0]['objectclass'])) {
260: $objectClassData = $user_info[0]['objectclass'];
261: }
262:
263:
264: unset($info['mode']);
265:
266:
267:
268: if (isset($info['password'])) {
269: if (!empty($user['password'])) {
270:
271: $info['user_password'] = Horde_Auth::getCryptedPassowrd($info['password'], '', 'ssha', true);
272: }
273: unset($info['password']);
274: }
275:
276: $tmp['dn'] = $addrinfo['id'];
277: foreach ($info as $key => $val) {
278: $attr = $this->_fieldmap[$key];
279: $tmp[$attr] = $val;
280: }
281:
282:
283: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
284: $this->_params['ldap']['bindpw']);
285: if (!$res) {
286: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
287: }
288:
289:
290: $entry['cn'] = $info['user_full_name'];
291:
292:
293: $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
294: $entry['mail'] = $info['user_name'] . $info['domain'];
295: $entry['uid'] = $entry['mail'];
296: $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
297: if ($type != 'group' && $type != 'forward') {
298: $entry['qmailUID'] = $entry['qmailGID'] = 8;
299: }
300: $entry['accountstatus'] = $info['user_enabled'];
301: if (isset($info['password']) && !empty($info['password'])) {
302:
303: $entry['userPassword'] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
304: }
305: if (isset($objectClassData)) {
306: array_shift($objectClassData);
307: $entry['objectclass'] = $objectClassData;
308: } else {
309: $entry['objectclass'] = array(
310: 'top',
311: 'person',
312: 'organizationalPerson',
313: 'inetOrgPerson',
314: 'hordePerson',
315: 'qmailUser');
316: }
317:
318:
319: try {
320: $entry = Horde::callHook('getLDAPAttrs', array($entry), 'vilma');
321: } catch (Horde_Exception_HookNotSet $e) {
322: }
323: $rdn = 'mail=' . $entry['mail'];
324: $dn = $rdn . ',' . $this->_params['ldap']['basedn'];
325: $res = @ldap_modify($this->_ldap, $dn, $entry);
326: if ($res === false) {
327: throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
328: }
329:
330: return $dn;
331: }
332:
333: 334: 335: 336: 337: 338: 339: 340:
341: protected function _createUser($info)
342: {
343:
344: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
345: $this->_params['ldap']['bindpw']);
346: if (!$res) {
347: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
348: }
349:
350:
351: $entry['cn'] = $info['user_full_name'];
352:
353:
354: $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
355: $entry['mail'] = $info['user_name'] . '@' . $info['domain'];
356:
357: $entry['uid'] = $entry['mail'];
358: $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
359: $entry['qmailUID'] = $entry['qmailGID'] = 8;
360: $entry['objectclass'] = array(
361: 'top',
362: 'person',
363: 'organizationalPerson',
364: 'inetOrgPerson',
365: 'hordePerson',
366: 'qmailUser');
367: $entry['accountstatus'] = $info['user_enabled'];
368:
369: $entry['userPassword'] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
370:
371:
372: try {
373: $entry = Horde::callHook('getLDAPAttrs', array($entry), 'vilma');
374: } catch (Horde_Exception_HookNotSet $e) {
375: }
376: $rdn = 'mail=' . $entry['mail'];
377: $dn = $rdn . ',' . $this->_params['ldap']['basedn'];
378: $res = @ldap_add($this->_ldap, $dn, $entry);
379: if ($res === false) {
380: throw new Vilma_Exception(sprintf(_("Error adding account to LDAP: %s"), @ldap_error($this->_ldap)));
381: }
382:
383: return $dn;
384: }
385:
386: 387: 388: 389: 390: 391: 392:
393: public function deleteUser($user_id)
394: {
395:
396: $filter = '(&';
397: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
398:
399: $filter .= '(objectclass=' . $objectclass . ')';
400: }
401: $filter .= '(mail=' . $user_id . ')';
402: $filter .= ')';
403:
404: Horde::logMessage($filter, 'DEBUG');
405: $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
406: if ($res === false) {
407: throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
408: }
409: $res = @ldap_get_entries($this->_ldap, $res);
410: if ($res === false) {
411: throw new Vilma_Exception(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
412: }
413:
414: if ($res['count'] === 0) {
415: throw new Vilma_Exception(_("Unable to acquire handle on DN. Aborting delete operation."));
416: }
417: if ($res['count'] !== 1) {
418: throw new Vilma_Exception(_("More than one DN returned. Aborting delete operation."));
419: }
420:
421:
422: $res = @ldap_delete($this->_ldap, $res[0]['dn']);
423: if ($res === false) {
424: throw new Vilma_Exception(sprintf(_("Error deleting account from LDAP: %s"), @ldap_error($this->_ldap)));
425: }
426: }
427:
428: public function getUserFormAttributes()
429: {
430: return array(array(
431: 'label' => _("Account Status"),
432: 'name' => 'user_enabled',
433: 'type' => 'enum',
434: 'required' => true,
435: 'readonly' => false,
436: 'description' => null,
437: 'params' => array(
438: array(
439: 'active' => _("Account is active"),
440: 'noaccess' => _("Disable Delivery Only"),
441: 'disabled' => _("Bounce Incoming Only"),
442: 'deleted' => _("Account is disabled"),
443: ),
444: ),
445: 'default' => 'active',
446: ));
447: }
448:
449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460:
461: protected function _getAddresses($domain, $type = 'all')
462: {
463: $addresses = array();
464: if ($type == 'all' || $type == 'user') {
465: $addresses += $this->_getUsers($domain);
466: }
467: if ($type == 'all' || $type == 'alias') {
468: $addresses += $this->_getAliases($domain);
469: }
470: if ($type == 'all' || $type == 'forward') {
471: $addresses += $this->_getGroupsAndForwards('forward', $domain);
472: }
473: if ($type == 'all' || $type == 'group') {
474: $addresses += $this->_getGroupsAndForwards('group', $domain);
475: }
476: return $addresses;
477: }
478:
479: 480: 481: 482: 483: 484: 485: 486: 487:
488: protected function _getAliases($target = null)
489: {
490:
491:
492:
493:
494: $filter = '(&';
495: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
496:
497: $filter .= '(objectClass=' . $objectclass . ')';
498: }
499:
500:
501: if (strpos($target, '@') === false && !empty($target)) {
502: $filter .= '(mailAlternateAddress=*@' . $target . ')';
503: } else {
504:
505: $filter .= '(mailAlternateAddress=*)';
506:
507: if (!empty($target)) {
508:
509: $filter .= '(mail=' . $target . ')';
510: }
511: }
512:
513: $filter .= ')';
514:
515: Horde::logMessage($filter, 'DEBUG');
516: $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
517: if ($res === false) {
518: throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
519: }
520:
521: $res = @ldap_get_entries($this->_ldap, $res);
522: if ($res === false) {
523: throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
524: }
525:
526: $aliases = array();
527:
528: for ($e = 0; isset($res[$e]); $entry = $res[$e++]) {
529:
530: if (!isset($entry[$this->_fieldmap['user_enabled']][0]) ||
531: $entry[$this->_fieldmap['user_enabled']][0] == 'active') {
532: $curstatus = 'active';
533: } else {
534:
535:
536:
537:
538: $curstatus = $entry[$this->_fieldmap['user_enabled']][0];
539: }
540: for ($a = 0; isset($entry['mailalternateaddress'][$a]); $mail = @$entry['mailalternateaddress'][$a++]) {
541: $aliases[] = array(
542: 'id' => $mail,
543: 'type' => 'alias',
544: 'user_name' => $mail,
545: 'user_full_name' => sprintf(_("Alias for %s"), $entry['mail'][0]),
546: 'destination' => $entry['mail'][0],
547: 'user_enabled' => $curstatus);
548: }
549: }
550:
551: return $aliases;
552: }
553:
554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567:
568: protected function _getGroupsAndForwards($acquire = null, $domain = null)
569: {
570:
571:
572: $filter = '(&';
573: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
574:
575: $filter .= '(objectClass=' . $objectclass . ')';
576: }
577:
578:
579: $filter .= '(mailForwardingAddress=*)';
580:
581: if (!empty($domain)) {
582:
583: $filter .= '(|';
584: $filter .= '(mail=*@' . $domain . ')';
585: $filter .= '(mailAlternateAddress=*@' . $domain . ')';
586: $filter .= ')';
587: } else {
588: $domain = '_all';
589: }
590:
591:
592: $filter .= ')';
593:
594: Horde::logMessage($filter, 'DEBUG');
595: $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
596: if ($res === false) {
597: throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
598: }
599:
600: $res = @ldap_get_entries($this->_ldap, $res);
601: if ($res === false) {
602: throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
603: }
604:
605: $grpfwds[$domain] = array();
606:
607: for ($e = 0; isset($res[$e]); $entry = $res[$e++]) {
608: $targets = array();
609: for ($a = 0; isset($res[$e]['mailforwardingaddress'][$a]); $attr = $res[$e]['mailforwardingaddress'][$a++]) {
610: $targets[] = $attr;
611: }
612: $type = $entry['mailforwardingaddress']['count'];
613: if ($type > 1) {
614: $type = 'group';
615: } else {
616: $type = 'forward';
617: }
618: if ($acquire == 'all' || $type == $acquire) {
619: $grpfwds[$domain][$e] = array(
620: 'id' => $entry['dn'],
621: 'type' => $type,
622: 'address' => $entry[$this->_fieldmap['address']][0],
623: 'targets' => $targets,
624: 'user_name' => $entry[$this->_fieldmap['user_name']][0],
625: 'user_full_name' => @$entry[$this->_fieldmap['user_name']][0],
626: );
627:
628: if (!isset($entry[$this->_fieldmap['user_enabled']][0]) ||
629: $entry[$this->_fieldmap['user_enabled']][0] == 'active') {
630: $grpfwds[$domain][$e]['user_enabled'] = 'active';
631: } else {
632:
633:
634:
635:
636: $grpfwds[$domain][$e]['user_enabled'] =
637: $entry[$this->_fieldmap['user_enabled']][0];
638: }
639: }
640: }
641:
642: return $grpfwds[$domain];
643: }
644:
645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656:
657: public function getAddressInfo($address, $type = 'all')
658: {
659: if ($type != 'alias') {
660: return parent::getAddressInfo($address, $type);
661: }
662:
663:
664:
665:
666: $filter = '(&';
667: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
668:
669: $filter .= '(objectClass=' . $objectclass . ')';
670: }
671: $filter .= '(mailAlternateAddress=' . $address . ')';
672:
673: $filter .= ')';
674:
675: Horde::logMessage($filter, 'DEBUG');
676: $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
677: if ($res === false) {
678: throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
679: }
680: $res = @ldap_get_entries($this->_ldap, $res);
681: if ($res === false) {
682: throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
683: }
684:
685: if ($res['count'] !== 1) {
686: throw new Vilma_Exception(_("More than one DN returned for this alias. Please contact an administrator to resolve this error."));
687: }
688:
689: return array(
690: 'id' => $res[0]['dn'],
691: 'address' => $address,
692: 'destination' => $res[0]['mail'][0],
693: );
694: }
695:
696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709:
710: public function saveAlias($info)
711: {
712: $address = $info['address'];
713: if (!empty($info['alias'])) {
714: $alias = $info['alias'];
715: $create = false;
716: } else {
717: $create = true;
718: }
719: $alias_address = $info['alias_address'];
720:
721: $user_res = $this->_searchForUser($address);
722: if ($res['count'] === 0) {
723: throw new Vilma_Exception(_("Error reading address information from backend."));
724: }
725: $user = $user_res[0];
726:
727:
728: if (isset($user_res[0]['mailalternateaddress'])) {
729: $maa = $user['mailalternateaddress'];
730: unset($maa['count']);
731: } else {
732: $maa = array();
733: }
734:
735: $oldmaa = $maa;
736: if ($create) {
737:
738: if (in_array($alias_address, $maa)) {
739: throw new Vilma_Exception(_("That alias already exists!"));
740: }
741:
742:
743: $maa[] = $alias_address;
744: } elseif ($alias != $alias_address) {
745: $key = array_search($alias, $maa);
746: if ($key === false) {
747: throw new Vilma_Exception(sprintf(_("Existing entry \"%s\" could not be found."), $alias));
748: }
749: $maa[$key] = $alias_address;
750: } else {
751: return;
752: }
753: sort($maa);
754:
755: $dn = $user['dn'];
756: Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
757:
758:
759: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
760: $this->_params['ldap']['bindpw']);
761: if (!$res) {
762: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
763: }
764:
765: $entry['mailAlternateAddress'] = $maa;
766: $res = @ldap_modify($this->_ldap, $dn, $entry);
767: if ($res === false) {
768: throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
769: }
770: }
771:
772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782:
783: public function deleteAlias($info)
784: {
785: $address = $info['address'];
786: $alias = $info['alias'];
787:
788: $user_res = $this->_searchForUser($address);
789: if ($res['count'] === 0) {
790: throw new Vilma_Exception(_("Error reading address information from backend."));
791: }
792: $user = $user_res[0];
793:
794:
795: if (!isset($user['mailalternateaddress'])) {
796: return;
797: }
798:
799: $maa = $user['mailalternateaddress'];
800: unset($maa['count']);
801: $oldmaa = $maa;
802: $key = array_search($alias, $maa);
803: if ($key === false) {
804: return;
805: }
806:
807: unset($maa[$key]);
808: sort($maa);
809:
810: $dn = $user['dn'];
811: Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
812:
813:
814: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
815: $this->_params['ldap']['bindpw']);
816: if (!$res) {
817: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
818: }
819:
820: $entry['mailAlternateAddress'] = $maa;
821: $res = @ldap_modify($this->_ldap, $dn, $entry);
822: if ($res === false) {
823: throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
824: }
825: }
826:
827: 828: 829: 830: 831: 832: 833: 834: 835: 836: 837: 838: 839: 840:
841: public function saveForward($info)
842: {
843: $address = $info['address'];
844: if (!empty($info['forward'])) {
845: $forward = $info['forward'];
846: $create = false;
847: } else {
848: $create = true;
849: }
850: $forward_address = $info['forward_address'];
851:
852: $user_res = $this->_searchForUser($address);
853: if ($res['count'] === 0) {
854: throw new Vilma_Exception(_("Error reading address information from backend."));
855: }
856: $user = $user_res[0];
857:
858:
859: if (isset($user['mailforwardingaddress'])) {
860: $mfa = $user['mailforwardingaddress'];
861: unset($mfa['count']);
862: } else {
863: $mfa = array();
864: }
865:
866: $oldmfa = $mfa;
867: if ($create) {
868:
869: if (in_array($forward_address, $mfa)) {
870: throw new Vilma_Exception(sprintf(_("That forward, \"%s\", already exists!"), $forward_address));
871: }
872:
873:
874: $mfa[] = $forward_address;
875: } elseif ($forward != $forward_address) {
876: $key = array_search($forward, $mfa);
877: if ($key === false) {
878: throw new Vilma_Exception(sprintf(_("Existing entry \"%s\" could not be found."), $forward));
879: }
880: $mfa[$key] = $forward_address;
881: } else {
882: return;
883: }
884: sort($mfa);
885:
886: $dn = $user['dn'];
887: Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
888:
889:
890: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
891: $this->_params['ldap']['bindpw']);
892: if (!$res) {
893: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
894: }
895:
896: $entry['mailForwardingAddress'] = $mfa;
897: $res = @ldap_modify($this->_ldap, $dn, $entry);
898: if ($res === false) {
899: throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
900: }
901: }
902:
903: 904: 905: 906: 907: 908: 909: 910: 911: 912: 913:
914: public function deleteForward($info)
915: {
916: $address = $info['address'];
917: $forward = $info['forward'];
918:
919: $user_res = $this->_searchForUser($address);
920: if ($res['count'] === 0) {
921: throw new Vilma_Exception(_("Error reading address information from backend."));
922: }
923: $user = $user_res[0];
924:
925:
926: if (!isset($user['mailforwardingaddress'])) {
927: return;
928: }
929:
930: $mfa = $user['mailforwardingaddress'];
931: unset($mfa['count']);
932: $oldmfa = $mfa;
933: $key = array_search($forward, $mfa);
934: if ($key === false) {
935: return;
936: }
937: unset($mfa[$key]);
938: sort($mfa);
939:
940: $dn = $user['dn'];
941: Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
942:
943: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
944: $this->_params['ldap']['bindpw']);
945: if (!$res) {
946: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
947: }
948:
949: $entry['mailForwardingAddress'] = $mfa;
950: $res = @ldap_modify($this->_ldap, $dn, $entry);
951: if ($res === false) {
952: throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
953: }
954: }
955:
956: 957: 958: 959: 960: 961: 962: 963:
964: protected function _searchForUser($email_id)
965: {
966:
967: $filter = '(&';
968: foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
969:
970: $filter .= '(objectclass=' . $objectclass . ')';
971: }
972: $filter .= '(mail=' . $email_id . '))';
973:
974: Horde::logMessage($filter, 'DEBUG');
975: $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
976: if ($res === false) {
977: throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
978: }
979: $res = @ldap_get_entries($this->_ldap, $res);
980: if ($res === false) {
981: throw new Vilma_Exception(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
982: }
983:
984: if ($res['count'] === 0) {
985: throw new Vilma_Exception(_("Unable to acquire handle on DN. Aborting delete operation."));
986: }
987: if($res['count'] !== 1) {
988: throw new Vilma_Exception(_("More than one DN returned. Aborting delete operation."));
989: }
990:
991: return $res;
992: }
993:
994: function _connect()
995: {
996: if (!is_null($this->_ldap)) {
997: return;
998: }
999:
1000: Horde::assertDriverConfig($this->_params['ldap'], 'storage',
1001: array('ldaphost', 'basedn', 'binddn', 'dn'));
1002:
1003: if (!isset($this->_params['ldap']['bindpw'])) {
1004: $this->_params['ldap']['bindpw'] = '';
1005: }
1006:
1007: $port = isset($this->_params['ldap']['port'])
1008: ? $this->_params['ldap']['port']
1009: : 389;
1010:
1011: $this->_ldap = ldap_connect($this->_params['ldap']['ldaphost'], $port);
1012: if (!$this->_ldap) {
1013: throw new Vilma_Exception("Unable to connect to LDAP server $hostname on $port");
1014: }
1015: $res = ldap_set_option($this->_ldap, LDAP_OPT_PROTOCOL_VERSION,
1016: $this->_params['ldap']['version']);
1017: if (!$res) {
1018: throw new Vilma_Exception(_("Unable to set LDAP protocol version"));
1019: }
1020: $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
1021: $this->_params['ldap']['bindpw']);
1022: if (!$res) {
1023: throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
1024: }
1025: }
1026: }
1027: