3 // @author Matt Todd <matt@matttoddphoto.com>
5 // @desc Handles LDAP authentication and information retreival
15 public $is_connected = false;
16 public $is_bound = false;
17 private $handlers = array();
18 private $results = array();
20 private $results_order = array();
23 public function __construct($config = null) {
24 $this->config
= (empty($config) ? Config2
::$config['adapters']['ldap'] : $config);
28 public function __get($name) {
29 $entry = current($this->results
);
32 public function as_array() {
33 return $this->results
;
36 // iteration and navigation
37 public function current() {
38 return current($this->results
);
40 public function next() {
44 public function previous() {
48 public function first() {
49 reset($this->results
);
52 public function last() {
58 protected function full_domain($username = null) {
59 foreach($this->config
['domain']['offices'] as $office) { // assemble offices
60 if(!empty($offices)) $offices .= ',';
61 $offices .= sprintf('OU=%s', $office);
63 if($username === null) return "{$offices},DC={$this->config[domain][subdomain]},DC={$this->config[domain][domain]},DC={$this->config[domain][top_level_domain]}";
64 return "CN={$username},{$offices},DC={$this->config[domain][subdomain]},DC={$this->config[domain][domain]},DC={$this->config[domain][top_level_domain]}";
66 protected function short_domain($username = null) {
67 if($username === null) return "{$this->config[domain][short_domain]}";
68 return "{$username}@{$this->config[domain][short_domain]}";
71 // clean results to a sensible structure
72 protected function clean($results) {
73 if(is_array($results)) {
74 // remove 'count' keys
75 if(!empty($results['count'])) unset($results['count']);
77 // if results has only one value, return it
78 if((count($results) == 1) && (!empty($results[0])) && (!is_array($results[0]))) {
82 // cleans repetitive data, et al
83 foreach($results as $key=>$entry) {
84 # (int)0 == "count", so we need to use ===
85 if($k = array_search($key, $results)) unset($results[$k]);
87 // remove all integer keys except for those with valuable data
88 if(is_int($key) && is_string($entry) && is_array($results[$entry])) {
89 unset($results[$key]);
94 if(is_array($entry)) {
95 $results[$key] = $this->clean($entry);
103 // overridden functions
104 public function connect() {
105 // connect to LDAP server
106 if(!($this->handlers
['connection'] = ldap_connect($this->config
['server']))) { // , 636
107 // could not connect to the LDAP server, throw error
108 throw new Exception("Could not connect to LDAP server {$this->config[server]}");
110 // ldap_set_option($this->handlers['connection'], LDAP_OPT_PROTOCOL_VERSION, 3);
111 // set connection status
112 $this->is_connected
= true;
116 public function user_bind($username, $password, $full_domain = false) {
117 // get proper username
118 // $username = (($full_domain) ? $this->full_domain($username) : $this->short_domain($username));
120 // set default bind status
123 // bind to LDAP server
124 // this takes the provided departments and if one level doesn't work, removes it and attempts to bind again
125 while($this->config
['domain']['offices']) {
126 if($this->handlers
['binding'] = @ldap_bind
($this->handlers
['connection'], $this->full_domain($username), $password)) {
130 array_shift($this->config
['domain']['offices']);
134 // could not bind to the server as $username
135 throw new Exception("Could not bind the LDAP server as <em>{$username}</em>");
137 // successfully connected and bound server as $username
138 $this->is_bound
= true;
142 public function bind($full_domain = false) {
143 // ldap reader binding
144 $username = $this->config
['domain']['reader']['username'];
145 $password = $this->config
['domain']['reader']['password'];
147 // bind to LDAP server
148 if(!($this->handlers
['binding'] = @ldap_bind
($this->handlers
['connection'], $username, $password))) {
149 // could not bind to the server as $username
150 throw new Exception("Could not bind the LDAP server as <em>{$username}</em>");
152 // successfully connected and bound server as $username
153 $this->is_bound
= true;
157 public function disconnect() {
158 // unbind/disconnect LDAP server
159 if(!(ldap_unbind($this->handlers
['connection']))) return false;
161 $this->is_bound
= false;
162 $this->is_connected
= false;
163 $this->handlers
['connection'] = null;
167 public function find($params, $full_domain = false) {
168 // remove previous results
169 $this->handlers
['results'] = null;
171 // set default params
172 $restrict_to = array();
176 // get settings from config
177 if(!empty($this->config
['restrict_to'])) $restrict_to = $this->config
['restrict_to'];
178 if(!empty($this->config
['filter'])) $filter = $this->config
['filter'];
179 if(!empty($this->config
['sort'])) $sort = $this->config
['sort'];
181 // get parameters for search
182 $domain = (($full_domain) ?
$this->full_domain() : $this->short_domain());
183 if(!empty($params['filter'])) $filter = $params['filter']; // such as: "(|(sn=$person*)(givenname=$person*))";
184 if(!empty($params['restrict_to'])) $restrict_to = $params['restrict_to']; // such as: array("ou", "sn", "givenname", "mail");
185 if(!empty($params['sort'])) $sort = $params['sort']; // such as: array("department", "sn");
188 $this->handlers
['results'] = @ldap_search
($this->handlers
['connection'], $domain, $filter, $restrict_to);
190 // if sort param set, sort results
192 foreach($sort as $key) {
193 @ldap_sort
($this->handlers
['connection'], $this->handlers
['results'], $key);
198 $results = @ldap_get_entries
($this->handlers
['connection'], $this->handlers
['results']);
201 $this->count
= $results['count'];
204 $results = $this->clean($results);
207 foreach($results as $key=>$entry) {
208 $this->results_order
[$key] = $entry['name'];
209 $this->results
[$entry['name']] = new entry($entry);
212 // remove results handle
213 $this->handlers
['results'] = array();
215 // return this object for more actions
218 public function locate($name) {
219 return $this->results
[$name];
221 public function save($entry, $params = null, $full_domain = false) {
224 public function insert($params, $entry, $full_domain = false) {
226 if(empty($params['domain'])) $domain = (($full_domain) ?
$this->full_domain() : $this->short_domain()); else $domain = $params['domain'];
229 if(!(ldap_add($this->handlers
['connection'], $domain, $entry))) return false;
233 public function update($params, $entry, $full_domain = false) {
235 if(empty($params['domain'])) $domain = (($full_domain) ?
$this->full_domain() : $this->short_domain()); else $domain = $params['domain'];
238 if(!(ldap_modify($this->handlers
['connection'], $domain, $entry))) return false;
242 public function delete($params, $full_domain = false) {
244 if(empty($params['domain'])) $domain = (($full_domain) ?
$this->full_domain() : $this->short_domain()); else $domain = $params['domain'];
247 if(!(ldap_delete($this->handlers
['connection'], $domain))) return false;
252 // retrieve LDAP error on failures
253 public function error() {
254 return ldap_error($this->handlers
['connection']);
259 private $properties = array();
262 public function __construct($properties) {
263 $this->properties
= $properties;
267 public function __get($name) {
268 return $this->properties
[$name];
270 public function as_array() {
271 return $this->properties
;