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