summaryrefslogtreecommitdiff
path: root/lib/Kolab/FreeBusy/DirectoryLDAP.php
blob: 00bba1a0e5eeb0f2e3e3513069d6fd4b20c2801f (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
<?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'],
			'log_hook'  => array($this, 'log'),
		) + $config;

		// instantiate Net_LDAP3 and connect with logger
		$this->logger = Logger::get('ldap', intval($config['loglevel']));
		$this->ldap = new Net_LDAP3($ldap_config);

		// 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('s' => $user);

		if ($this->ready) {
			// search with configured filter
			$filter = preg_replace('/%s/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;
	}

}