1<?php
2/**
3 * PHP LDAP CLASS FOR MANIPULATING ACTIVE DIRECTORY
4 * Version 4.0.4
5 *
6 * PHP Version 5 with SSL and LDAP support
7 *
8 * Written by Scott Barnett, Richard Hyland
9 *   email: scott@wiggumworld.com, adldap@richardhyland.com
10 *   http://adldap.sourceforge.net/
11 *
12 * Copyright (c) 2006-2012 Scott Barnett, Richard Hyland
13 *
14 * We'd appreciate any improvements or additions to be submitted back
15 * to benefit the entire community :)
16 *
17 * This library is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Lesser General Public
19 * License as published by the Free Software Foundation; either
20 * version 2.1 of the License.
21 *
22 * This library is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25 * Lesser General Public License for more details.
26 *
27 * @category ToolsAndUtilities
28 * @package adLDAP
29 * @subpackage Contacts
30 * @author Scott Barnett, Richard Hyland
31 * @copyright (c) 2006-2012 Scott Barnett, Richard Hyland
32 * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html LGPLv2.1
33 * @revision $Revision: 97 $
34 * @version 4.0.4
35 * @link http://adldap.sourceforge.net/
36 */
37
38require_once(dirname(__FILE__).'/../adLDAP.php');
39require_once(dirname(__FILE__).'/../collections/adLDAPContactCollection.php');
40
41class adLDAPContacts {
42    /**
43     * The current adLDAP connection via dependency injection
44     *
45     * @var adLDAP
46     */
47    protected $adldap;
48
49    public function __construct(adLDAP $adldap) {
50        $this->adldap = $adldap;
51    }
52
53    //*****************************************************************************************************************
54    // CONTACT FUNCTIONS
55    // * Still work to do in this area, and new functions to write
56
57    /**
58    * Create a contact
59    *
60    * @param array $attributes The attributes to set to the contact
61    * @return string|boolean
62    */
63    public function create($attributes)
64    {
65        // Check for compulsory fields
66        if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
67        if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
68        if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
69        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
70
71        // Translate the schema
72        $add = $this->adldap->adldap_schema($attributes);
73
74        // Additional stuff only used for adding contacts
75        $add["cn"][0] = $attributes["display_name"];
76        $add["objectclass"][0] = "top";
77        $add["objectclass"][1] = "person";
78        $add["objectclass"][2] = "organizationalPerson";
79        $add["objectclass"][3] = "contact";
80        if (!isset($attributes['exchange_hidefromlists'])) {
81            $add["msExchHideFromAddressLists"][0] = "TRUE";
82        }
83
84        // Determine the container
85        $attributes["container"] = array_reverse($attributes["container"]);
86        $container = "OU=".implode(",OU=", $attributes["container"]);
87
88        // Add the entry
89        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=".$this->adldap->utilities()->escapeCharacters($add["cn"][0]).", ".$container.",".$this->adldap->getBaseDn(), $add);
90        if ($result != true) {
91            return false;
92        }
93
94        return true;
95    }
96
97    /**
98    * Determine the list of groups a contact is a member of
99    *
100    * @param string $distinguishedName The full DN of a contact
101    * @param bool $recursive Recursively check groups
102    * @return array
103    */
104    public function groups($distinguishedName, $recursive = NULL)
105    {
106        if ($distinguishedName === NULL) { return false; }
107        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
108        if (!$this->adldap->getLdapBind()) { return false; }
109
110        // Search the directory for their information
111        $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
112        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
113
114        if ($recursive === true) {
115            foreach ($groups as $id => $groupName) {
116                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
117                $groups = array_merge($groups, $extraGroups);
118            }
119        }
120
121        return $groups;
122    }
123
124    /**
125    * Get contact information. Returned in a raw array format from AD
126    *
127    * @param string $distinguishedName The full DN of a contact
128    * @param array $fields Attributes to be returned
129    * @return array
130    */
131    public function info($distinguishedName, $fields = NULL)
132    {
133        if ($distinguishedName === NULL) { return false; }
134        if (!$this->adldap->getLdapBind()) { return false; }
135
136        $filter = "distinguishedName=".$distinguishedName;
137        if ($fields === NULL) {
138            $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid");
139        }
140        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
141        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
142
143        if ($entries[0]['count'] >= 1) {
144            // AD does not return the primary group in the ldap query, we may need to fudge it
145            if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])) {
146                //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
147                $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
148            } else {
149                $entries[0]["memberof"][] = "CN=Domain Users,CN=Users,".$this->adldap->getBaseDn();
150            }
151        }
152
153        $entries[0]["memberof"]["count"]++;
154        return $entries;
155    }
156
157    /**
158     * Find information about the contacts. Returned in a raw array format from AD
159     *
160     * @param string $distinguishedName The full DN of a contact
161     * @param array $fields Array of parameters to query
162     * @return mixed
163     */
164    public function infoCollection($distinguishedName, $fields = NULL)
165    {
166        if ($distinguishedName === NULL) { return false; }
167        if (!$this->adldap->getLdapBind()) { return false; }
168
169        $info = $this->info($distinguishedName, $fields);
170
171        if ($info !== false) {
172            $collection = new adLDAPContactCollection($info, $this->adldap);
173            return $collection;
174        }
175        return false;
176    }
177
178    /**
179     * Determine if a contact is a member of a group
180     *
181     * @param string $distinguisedName The full DN of a contact
182     * @param string $group The group name to query
183     * @param bool $recursive Recursively check groups
184     * @return bool
185     */
186    public function inGroup($distinguisedName, $group, $recursive = NULL)
187    {
188        if ($distinguisedName === NULL) { return false; }
189        if ($group === NULL) { return false; }
190        if (!$this->adldap->getLdapBind()) { return false; }
191        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
192
193        // Get a list of the groups
194        $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
195
196        // Return true if the specified group is in the group list
197        if (in_array($group, $groups)) {
198            return true;
199        }
200
201        return false;
202    }
203
204    /**
205    * Modify a contact
206    *
207    * @param string $distinguishedName The contact to query
208    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
209    * @return string|boolean
210    */
211    public function modify($distinguishedName, $attributes) {
212        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
213
214        // Translate the update to the LDAP schema
215        $mod = $this->adldap->adldap_schema($attributes);
216
217        // Check to see if this is an enabled status update
218        if (!$mod) {
219            return false;
220        }
221
222        // Do the update
223        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
224        if ($result == false) {
225            return false;
226        }
227
228        return true;
229    }
230
231    /**
232    * Delete a contact
233    *
234    * @param string $distinguishedName The contact dn to delete (please be careful here!)
235    * @return boolean
236    */
237    public function delete($distinguishedName)
238    {
239        $result = $this->folder()->delete($distinguishedName);
240        if ($result != true) {
241            return false;
242        }
243        return true;
244    }
245
246    /**
247     * Return a list of all contacts
248     *
249     * @param bool $includeDescription Include a description of a contact
250     * @param string $search The search parameters
251     * @param bool $sorted Whether to sort the results
252     * @return array
253     */
254    public function all($includeDescription = false, $search = "*", $sorted = true) {
255        if (!$this->adldap->getLdapBind()) { return false; }
256
257        // Perform the search and grab all their details
258        $filter = "(&(objectClass=contact)(cn=".$search."))";
259        $fields = array("displayname", "distinguishedname");
260        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
261        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
262
263        $usersArray = array();
264        for ($i = 0; $i < $entries["count"]; $i++) {
265            if ($includeDescription && strlen($entries[$i]["displayname"][0]) > 0) {
266                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
267            } elseif ($includeDescription) {
268                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
269            } else {
270                array_push($usersArray, $entries[$i]["distinguishedname"][0]);
271            }
272        }
273        if ($sorted) {
274            asort($usersArray);
275        }
276        return $usersArray;
277    }
278
279    /**
280    * Mail enable a contact
281    * Allows email to be sent to them through Exchange
282    *
283    * @param string $distinguishedName The contact to mail enable
284    * @param string $emailAddress The email address to allow emails to be sent through
285    * @param string $mailNickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
286    * @return string|boolean
287    */
288    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL) {
289        return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
290    }
291
292
293}
294?>
295