summaryrefslogtreecommitdiff
path: root/lib/Kolab/FreeBusy/DirectoryLDAP.php
blob: 1c675f98da6aee0d0a3a1337413ef60206153c0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php

namespace Kolab\FreeBusy;

// PEAR modules operate in global namespace
use \Net_LDAP3;
use \Monolog\Logger as Monolog;

/**
 *
 */
class DirectoryLDAP extends Directory
{
	private $ldap;
	private $logger;
	private $ready = false;

	/**
	 * Default constructor loading directory configuration
	 */
	public function __construct($config)
	{
		$this->config = $config;

		$host = parse_url($config['host']);
		$ldap_config = array(
			'hosts'     => array($host['host']),
			'port'      => $host['port'] ?: 389,
			'use_tls'   => $host['scheme'] == 'tls' || $host['scheme'] == 'ldaps',
			'root_dn'   => $config['base_dn'],
			'return_attributes' => (array)$config['attributes'],
			'sizelimit' => 0,
			'timelimit' => 0,
		) + $config;

		// instantiate Net_LDAP3 and connect with logger
		$this->logger = Logger::get('ldap', $config['loglevel']);
		$this->ldap = new Net_LDAP3($ldap_config);
		$this->ldap->config_set('log_hook', array($this, 'log'));
		$this->ldap->config_set('return_attributes', (array)$config['attributes']);

		// connect + bind to LDAP server
		if ($this->ldap->connect()) {
			$this->ready = $this->ldap->bind($config['bind_dn'], $config['bind_pw']);
		}

		if ($this->ready) {
			$this->logger->addInfo("Connected to $config[host] with '$config[bind_dn]'");
		}
		else {
			$this->logger->addWarning("Connectiion to $config[host] with '$config[bind_dn]' failed!");
		}
	}

	/**
	 * Callback for Net_LDAP3 logging
	 */
	public function log($level, $msg)
	{
		// map PHP log levels to Monolog levels
		static $loglevels = array(
			LOG_DEBUG   => Monolog::DEBUG,
			LOG_NOTICE  => Monolog::NOTICE,
			LOG_INFO    => Monolog::INFO,
			LOG_WARNING => Monolog::WARNING,
			LOG_ERR     => Monolog::ERROR,
			LOG_CRIT    => Monolog::CRITICAL,
			LOG_ALERT   => Monolog::ALERT,
			LOG_EMERG   => Monolog::EMERGENCY,
		);

		$msg = is_array($msg) ? join('; ', $msg) : strval($msg);
		$this->logger->addRecord($loglevels[$level], $msg);
	}

	/**
	 * @see Directory::resolve()
	 */
	public function resolve($user)
	{
		$result = array('u' => $user);

		if ($this->ready) {
			// search with configured filter
			$filter = preg_replace('/%u/i', $user, $this->config['filter']);
			$ldapresult = $this->ldap->search($this->config['base_dn'], $filter, 'sub');

			// got a valid result
			if ($ldapresult && $ldapresult->count()) {
				$ldapresult->rewind();
				$entry = Net_LDAP3::normalize_entry($ldapresult->current());  // get the first entry
				$this->logger->addInfo("Found " . $ldapresult->count() . " entries for $filter", $entry);

				// convert entry attributes to strings and add them to the final result hash array
				foreach ($entry as $k => $v) {
					if (!empty($v)) {
						$result[$k] = strval(is_array($v) ? $v[0] : $v);
					}
				}

				return $result;
			}

			$this->logger->addInfo("No entry found for $filter");
		}

		return false;
	}

}