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
41use dokuwiki\Utf8\Sort;
42
43class adLDAPContacts {
44    /**
45    * The current adLDAP connection via dependency injection
46    *
47    * @var adLDAP
48    */
49    protected $adldap;
50
51    public function __construct(adLDAP $adldap) {
52        $this->adldap = $adldap;
53    }
54
55    //*****************************************************************************************************************
56    // CONTACT FUNCTIONS
57    // * Still work to do in this area, and new functions to write
58
59    /**
60    * Create a contact
61    *
62    * @param array $attributes The attributes to set to the contact
63    * @return bool
64    */
65    public function create($attributes)
66    {
67        // Check for compulsory fields
68        if (!array_key_exists("display_name", $attributes)) { return "Missing compulsory field [display_name]"; }
69        if (!array_key_exists("email", $attributes)) { return "Missing compulsory field [email]"; }
70        if (!array_key_exists("container", $attributes)) { return "Missing compulsory field [container]"; }
71        if (!is_array($attributes["container"])) { return "Container attribute must be an array."; }
72
73        // Translate the schema
74        $add = $this->adldap->adldap_schema($attributes);
75
76        // Additional stuff only used for adding contacts
77        $add["cn"][0] = $attributes["display_name"];
78        $add["objectclass"][0] = "top";
79        $add["objectclass"][1] = "person";
80        $add["objectclass"][2] = "organizationalPerson";
81        $add["objectclass"][3] = "contact";
82        if (!isset($attributes['exchange_hidefromlists'])) {
83            $add["msExchHideFromAddressLists"][0] = "TRUE";
84        }
85
86        // Determine the container
87        $attributes["container"] = array_reverse($attributes["container"]);
88        $container= "OU=" . implode(",OU=", $attributes["container"]);
89
90        // Add the entry
91        $result = @ldap_add($this->adldap->getLdapConnection(), "CN=" . $this->adldap->utilities()->escapeCharacters($add["cn"][0]) . ", " . $container . "," . $this->adldap->getBaseDn(), $add);
92        if ($result != true) {
93            return false;
94        }
95
96        return true;
97    }
98
99    /**
100    * Determine the list of groups a contact is a member of
101    *
102    * @param string $distinguisedname The full DN of a contact
103    * @param bool $recursive Recursively check groups
104    * @return array
105    */
106    public function groups($distinguishedName, $recursive = NULL)
107    {
108        if ($distinguishedName === NULL) { return false; }
109        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
110        if (!$this->adldap->getLdapBind()){ return false; }
111
112        // Search the directory for their information
113        $info = @$this->info($distinguishedName, array("memberof", "primarygroupid"));
114        $groups = $this->adldap->utilities()->niceNames($info[0]["memberof"]); //presuming the entry returned is our contact
115
116        if ($recursive === true){
117            foreach ($groups as $id => $groupName){
118                $extraGroups = $this->adldap->group()->recursiveGroups($groupName);
119                $groups = array_merge($groups, $extraGroups);
120            }
121        }
122
123        return $groups;
124    }
125
126    /**
127    * Get contact information. Returned in a raw array format from AD
128    *
129    * @param string $distinguisedname The full DN of a contact
130    * @param array $fields Attributes to be returned
131    * @return array
132    */
133    public function info($distinguishedName, $fields = NULL)
134    {
135        if ($distinguishedName === NULL) { return false; }
136        if (!$this->adldap->getLdapBind()) { return false; }
137
138        $filter = "distinguishedName=" . $distinguishedName;
139        if ($fields === NULL) {
140            $fields = array("distinguishedname", "mail", "memberof", "department", "displayname", "telephonenumber", "primarygroupid", "objectsid");
141        }
142        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
143        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
144
145        if ($entries[0]['count'] >= 1) {
146            // AD does not return the primary group in the ldap query, we may need to fudge it
147            if ($this->adldap->getRealPrimaryGroup() && isset($entries[0]["primarygroupid"][0]) && isset($entries[0]["primarygroupid"][0])){
148                //$entries[0]["memberof"][]=$this->group_cn($entries[0]["primarygroupid"][0]);
149                $entries[0]["memberof"][] = $this->adldap->group()->getPrimaryGroup($entries[0]["primarygroupid"][0], $entries[0]["objectsid"][0]);
150            } else {
151                $entries[0]["memberof"][] = "CN=Domain Users,CN=Users," . $this->adldap->getBaseDn();
152            }
153        }
154
155        $entries[0]["memberof"]["count"]++;
156        return $entries;
157    }
158
159    /**
160    * Find information about the contacts. Returned in a raw array format from AD
161    *
162    * @param string $distinguishedName The full DN of a contact
163    * @param array $fields Array of parameters to query
164    * @return mixed
165    */
166    public function infoCollection($distinguishedName, $fields = NULL)
167    {
168        if ($distinguishedName === NULL) { return false; }
169        if (!$this->adldap->getLdapBind()) { return false; }
170
171        $info = $this->info($distinguishedName, $fields);
172
173        if ($info !== false) {
174            $collection = new adLDAPContactCollection($info, $this->adldap);
175            return $collection;
176        }
177        return false;
178    }
179
180    /**
181    * Determine if a contact is a member of a group
182    *
183    * @param string $distinguisedName The full DN of a contact
184    * @param string $group The group name to query
185    * @param bool $recursive Recursively check groups
186    * @return bool
187    */
188    public function inGroup($distinguisedName, $group, $recursive = NULL)
189    {
190        if ($distinguisedName === NULL) { return false; }
191        if ($group === NULL) { return false; }
192        if (!$this->adldap->getLdapBind()) { return false; }
193        if ($recursive === NULL) { $recursive = $this->adldap->getRecursiveGroups(); } //use the default option if they haven't set it
194
195        // Get a list of the groups
196        $groups = $this->groups($distinguisedName, array("memberof"), $recursive);
197
198        // Return true if the specified group is in the group list
199        if (in_array($group, $groups)){
200            return true;
201        }
202
203        return false;
204    }
205
206    /**
207    * Modify a contact
208    *
209    * @param string $distinguishedName The contact to query
210    * @param array $attributes The attributes to modify.  Note if you set the enabled attribute you must not specify any other attributes
211    * @return bool
212    */
213    public function modify($distinguishedName, $attributes) {
214        if ($distinguishedName === NULL) { return "Missing compulsory field [distinguishedname]"; }
215
216        // Translate the update to the LDAP schema
217        $mod = $this->adldap->adldap_schema($attributes);
218
219        // Check to see if this is an enabled status update
220        if (!$mod) {
221            return false;
222        }
223
224        // Do the update
225        $result = ldap_modify($this->adldap->getLdapConnection(), $distinguishedName, $mod);
226        if ($result == false) {
227            return false;
228        }
229
230        return true;
231    }
232
233    /**
234    * Delete a contact
235    *
236    * @param string $distinguishedName The contact dn to delete (please be careful here!)
237    * @return array
238    */
239    public function delete($distinguishedName)
240    {
241        $result = $this->folder()->delete($distinguishedName);
242        if ($result != true) {
243            return false;
244        }
245        return true;
246    }
247
248    /**
249    * Return a list of all contacts
250    *
251    * @param bool $includeDescription Include a description of a contact
252    * @param string $search The search parameters
253    * @param bool $sorted Whether to sort the results
254    * @return array
255    */
256    public function all($includeDescription = false, $search = "*", $sorted = true) {
257        if (!$this->adldap->getLdapBind()) { return false; }
258
259        // Perform the search and grab all their details
260        $filter = "(&(objectClass=contact)(cn=" . $search . "))";
261        $fields = array("displayname","distinguishedname");
262        $sr = ldap_search($this->adldap->getLdapConnection(), $this->adldap->getBaseDn(), $filter, $fields);
263        $entries = ldap_get_entries($this->adldap->getLdapConnection(), $sr);
264
265        $usersArray = array();
266        for ($i=0; $i<$entries["count"]; $i++){
267            if ($includeDescription && strlen($entries[$i]["displayname"][0])>0){
268                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["displayname"][0];
269            } elseif ($includeDescription){
270                $usersArray[$entries[$i]["distinguishedname"][0]] = $entries[$i]["distinguishedname"][0];
271            } else {
272                array_push($usersArray, $entries[$i]["distinguishedname"][0]);
273            }
274        }
275        if ($sorted) {
276            Sort::asort($usersArray);
277        }
278        return $usersArray;
279    }
280
281    /**
282    * Mail enable a contact
283    * Allows email to be sent to them through Exchange
284    *
285    * @param string $distinguishedname The contact to mail enable
286    * @param string $emailaddress The email address to allow emails to be sent through
287    * @param string $mailnickname The mailnickname for the contact in Exchange.  If NULL this will be set to the display name
288    * @return bool
289    */
290    public function contactMailEnable($distinguishedName, $emailAddress, $mailNickname = NULL){
291        return $this->adldap->exchange()->contactMailEnable($distinguishedName, $emailAddress, $mailNickname);
292    }
293
294
295}
296?>
297