source: trunk/contactcenter/inc/class.bo_ldap_manager.inc.php @ 4538

Revision 4538, 19.2 KB checked in by airton, 13 years ago (diff)

Ticket #1934 - Parametrização das buscas LDAP no Contactcenter

  • Property svn:eol-style set to native
  • Property svn:executable set to *
RevLine 
[2]1<?php
2  /***************************************************************************\
3  * eGroupWare - Contacts Center                                              *
4  * http://www.egroupware.org                                                 *
5  * Written by:                                                               *
6  *  - Raphael Derosso Pereira <raphaelpereira@users.sourceforge.net>         *
7  * ------------------------------------------------------------------------- *
8  *  This program is free software; you can redistribute it and/or modify it  *
9  *  under the terms of the GNU General Public License as published by the    *
10  *  Free Software Foundation; either version 2 of the License, or (at your   *
11  *  option) any later version.                                               *
12  \***************************************************************************/
13
[285]14       
[2]15        /*
16                This class is responsible for the LDAP control/generic functions and for
17                configuration gathering
18        */
[284]19        include_once('class.Thread.inc.php');
[2]20
[285]21        class bo_ldap_manager
[2]22        {
[285]23               
[2]24                var $srcs;
25
[285]26               
[2]27                function bo_ldap_manager ()
28                {
29                        if (!($this->srcs = $GLOBALS['phpgw']->session->appsession('bo_ldap_manager.srcs','contactcenter')))
30                        {
31                                $c = CreateObject('phpgwapi.config','contactcenter');
32                                $data = $c->read_repository();
[285]33                               
[2]34                                if (!$data or $data['cc_global_source0'] !== 'ldap')
35                                {
36                                        $this->srcs = null;
37                                        return;
38                                }
[285]39                               
[3262]40                                $ou = '';
[3288]41                                $subLevels = 'false';
42
43                                if( (!isset($data['cc_ldap_subLevels'])) || ($data['cc_ldap_subLevels'] == "true") )
[3262]44                                {
45                                        $ou = strtolower('ou');
[3288]46                                        $subLevels = 'true';
[3262]47                                }
48
[2]49                                $this->srcs = array(
50                                        1 => array(
51                                                'name'   => $data['cc_catalog_name'],
52                                                'host'   => $data['cc_ldap_host0'],
53                                                'dn'     => $data['cc_ldap_context0'],
54                                                'acc'    => $data['cc_ldap_browse_dn0'],
55                                                'pw'     => $data['cc_ldap_pw0'],
[4305]56                                                'obj'    => 'phpgwAccount',
[3262]57                                                'branch' => $ou, //strtolower('ou'),
[3288]58                                                'montaDN'=> $subLevels, //$data['cc_ldap_subLevels'],
[4538]59                                                'visible'=> $data['cc_ldap_query_automatic'],
60                                                'max_results' => $data['cc_ldap_max_results']
[2]61                                        )
62                                );
63                        }
64                }
65
66                function new_ldap_source ( $source_name, $charset, $host, $port, $dn_root, $dn_admin, $admin_pass, $contact_objectclass )
67                {
68                }
[285]69       
[2]70                /*
[285]71               
[2]72                        @function get_all_ldap_sources
73                        @abstract Returns an array containing all LDAP sources informations
74                        @author Raphael Derosso Pereira
[285]75               
[2]76                        @return array All LDAP information
77                                $return = array(
78                                        <id_source> => array(
79                                                'host' => (string),
80                                                'dn'   => (string),
81                                                'acc'  => (string),
[285]82                                                'pw'   => (string)   
[2]83                                        ),
84                                        ...
85                                )
[285]86                               
[2]87                        TODO: Return multiple sources...
88                */
89                function get_all_ldap_sources (  )
90                {
91                        return $this->srcs;
92                }
[285]93               
[284]94                /*
95                * @function get_external_ldap_sources
[4538]96                * @author Mário César Kolling <mario.kolling@serpro.gov.br>
[284]97                * @abstract returns an array with the external sources
98                * @return (array) the external sources
99                */
100
101                function get_external_ldap_sources()
102                {
103                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' );
104                        //include('external_catalogs.inc.php' );
105                        return $external_srcs;
106                }
107
108                /*
109                 * @function get_ldap_fields_association
110                 * @abstract get the fields associantion for ldap source
111                 * @return an array with attribute mappings
112                 */
[2]113                function get_ldap_fields_association ( $id_source )
114                {
[285]115                       
[2]116                        $op_iop = array(
[1600]117                                'contact.uidnumber'                => array('uidNumber'),
[2]118                                'contact.id_contact'               => array('dn'),
119                                'contact.photo'                    => array('jpegPhoto'),
120                                'contact.prefixes.prefix'          => false,
121                                'contact.alias'                    => array('alias'),
122                                'contact.given_names'              => array('givenName'),
123                                'contact.family_names'             => array('sn'),
124                                'contact.names_ordered'            => array('cn'),//,'displayName'),
125                                'contact.suffixes.suffix'          => false,
126                                'contact.birthdate'                => false,
127                                'contact.sex'                      => false,
128                                'contact.pgp_key'                  => false,
129                                'contact.notes'                    => false,
[285]130                                'contact.mail_forwarding_address' => array('mailForwardingAddress'),
131                                'contact.account_type' => array('phpgwAccountType'),
132                'contact.account_status'           => array('phpgwAccountStatus'),
133                'contact.account_visible'          => array('phpgwAccountVisible'),
[284]134                                'contact.object_class'             => array('objectClass'),
[2]135                                'contact.business_info.title'      => array('title'),
[1600]136                                'contact.business_info.department' => array('ou'), // Setor do empregado...
137                                'contact.business_info.empNumber'  => array('employeeNumber'), // Matricula do empregado
138
139                                'contact.business_info.celPhone'   => array('mobile'), // Celular empresarial do empregado
140
141                                'contact.company.company_name'     => array('o'),
[2]142                                'contact.company.company_notes'    => array('businessCategory'),
[285]143                               
[2]144                                'contact.contact_related.names_ordered' => 'contact.contact_related.typeof_relation.contact_relation_name',
145                                'contact.contact_related.typeof_relation.contact_relation_name' =>  array(
146                                        'manager'   => array('manager'),
147                                        'secretary' => array('secretary')
148                                ),
[285]149                               
[2]150                                'contact.address.address1'         => 'contact.address.typeof_address.contact_address_type_name',
151                                'contact.address.typeof_address.contact_address_type_name' => array(
152                                        'home' => array('street', 'st', 'postalAddress', 'homePostalAddress'),
153                                ),
[285]154                               
[2]155                                'contact.address.postal_code'      => 'contact.address.typeof_address.contact_address_type_name',
156                                'contact.address.typeof_address.contact_address_type_name' => array(
157                                        'home' => array('PostalCode'),
158                                ),
[285]159                               
[2]160                                'contact.address.city.city_name'   => 'contact.address.typeof_address.contact_address_type_name',
161                                'contact.address.typeof_address.contact_address_type_name' => array(
162                                        'home' => array('l'),
163                                ),
[285]164                               
[2]165                                'contact.address.city.state.state_name'       => 'contact.address.typeof_address.contact_address_type_name',
166                                'contact.address.typeof_address.contact_address_type_name' => array(
167                                        'home' => false,
168                                ),
[285]169                               
[2]170                                'contact.address.city.country.id_country'     => 'contact.address.typeof_address.contact_address_type_name',
171                                'contact.address.typeof_address.contact_address_type_name' => array(
172                                        'home' => array('c')
173                                ),
[285]174                               
[2]175                                'contact.connection.connection_value'         => 'contact.connection.typeof_connection.contact_connection_type_name',
176                                'contact.connection.typeof_connection.contact_connection_type_name' => array (
177                                        'email'  => array('mail'),
178                                        'phone'  => array('telephoneNumber'),
[1600]179                                //      'mobile' => array('mobile'),
180                                //      'pager'  => array('pager'), // idem ao comentario abaixo, do atributo fax;
181                                //      'fax'    => array('facsimileTelephoneNumber'), //linha comentada para nao trazer
182                                // o atributo fax do Ldap; correcao temporaria para nao exibir o fax no ContactCenter
183                                //(estava sobrepondo o telefone do usuario)
184
[2]185                                        'telex'  => array('telexNumber')
186                                ),
[3282]187                                'contact.connection.mail'                                  => array('mail'),
188                                'contact.connection.phone'                                 => array('telephoneNumber')
[2]189                        );
[285]190                       
[2]191                        return $op_iop;
192                }
193
[284]194                /*
195                 * @function get_external_ldap_fields_association
[4500]196                 * @author Mário César Kolling <mario.kolling@serpro.gov.br>
[284]197                 * @abstract get the fields association for an external ldap_source
198                 * @return an array with attribute mappings
199                 */
200                function get_external_ldap_fields_association ( $id_source )
201                {
202                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' );
203                        //include('external_catalogs.inc.php' );
204                        return $external_mappings[$id_source];
205                }
206
207                /*
208                 * @function test_connection
[4500]209                 * @author Mário César Kolling <mario.kolling@serpro.gov.br>
[284]210                 * @abstract Test if we can bind to a ldap server in a reasonable time
211                 * @param (string) $host ldap server's hostname
212                 * @param (string) $account ldap bind dn
213                 * @param (string) $password a bind dn's password
214                 * @return (array) an array with the answer from the subprocess, null otherwise
215                 */
216                function test_connection($host, $account, $password, $timeout = 5)
217                {
218                        //opens a subprocess for nonblocking bind
219                        $tsearch = Thread::Create('class.ldap_assync.inc.php', array('host'     => $host,
220                                                                                                                                'account'       => $account,
221                                                                                                                                'password'      => $password
222                                                                                                                                )
223                        );
224
225                        // It's problably more efficient to let method readResponse control the timeout through
226                        // stream_select native timeout.
227                        $response = NULL;
228                        for ($i = 0; $i < $timeout; $i++)
229                        {
230                                if ($tsearch->isActive())
231                                {
232                                        sleep(1);
233                                        if (($response = $tsearch->readResponse()) !== NULL)
234                                        {
235                                                $tsearch->close();
236                                                return $response;
237                                        }
238
239                                }
240                                else
241                                {
242                                        $response = $tsearch->readResponse();
243                                        break;
244                                }
245                        }
246
247                        $tsearch->close();
248                        return null;
249                }
250
[2]251                /*!
[285]252               
[2]253                        @function get_ldap_tree
254                        @abstract Returns the LDAP tree corresponding to the specified level
255                        @author Raphael Derosso Pereira
[285]256                       
[2]257                        @param (integer) $id_source The ID of the LDAP source
[285]258                       
[2]259                        @param (string)  $context The context to be used as root branch
[285]260                               
[2]261                        @param (boolean) $recursive Make it a recursive construction.
262                                CAUTION! This is EXTREMELY SLOW on large LDAP databases,
263                                specially when they're not indexed
[285]264                */             
265                function get_ldap_tree($id_source, $context = false, $recursive = false)
[2]266                {
267                        if (!$this->srcs[$id_source])
268                        {
269                                return null;
270                        }
[285]271                       
[4352]272                        $ldap = $GLOBALS['phpgw']->common->ldapConnect($this->srcs[$id_source]['host'], $this->srcs[$id_source]['acc'],$this->srcs[$id_source]['pw'], true);
[2]273                        if (!$ldap)
274                        {
275                                return false;
276                        }
[285]277                       
[2]278                        if ($recursive)
279                        {
280                                $tree = $this->get_ldap_tree_recursive($ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch']);
281                                $tree['recursive'] = true;
282
283                                return $tree;
284                        }
[285]285                       
286                        return $this->get_ldap_tree_level($id_source, $ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch']);
[2]287                }
[285]288                // SERPRO
[2]289
[284]290                /*!
[2]291
[284]292                        @function get_external_ldap_tree
293                        @abstract Returns the LDAP external tree corresponding to the specified level
[4500]294                        @author Mário César Kolling <mario.kolling@serpro.gov.br>
[284]295                        @param (integer) $id_source The ID of the external LDAP source
296                        @param (string)  $context The context to be used as root branch
297                        @param (boolean) $recursive Make it a recursive construction.
298                                CAUTION! This is EXTREMELY SLOW on large LDAP databases,
299                                specially when they're not indexed
300                */
301                function get_external_ldap_tree($id_source, $context = false, $recursive = false)
302                {
303
304
305                        include(PHPGW_INCLUDE_ROOT . '/contactcenter/setup/external_catalogs.inc.php' );
306                        //include('external_catalogs.inc.php' );
[1600]307
[284]308                        if (!$external_srcs[$id_source])
309                        {
310                                return null;
311                        }
[1600]312
[284]313                        // calls test_connection first. If succeeded continue, return error message otherwise.
314                        if (!($response = $this->test_connection($external_srcs[$id_source]['host'], $external_srcs[$id_source]['acc'], $external_srcs[$id_source]['pw'], 10)))
315                        {
316                                return array(
317                                        'msg'           =>      lang("Catalog %1 temporarily unavailable. Please try again later!", $external_srcs[$id_source]['name']),
318                                        'timeout'       =>      'true'
319                                );
320                        }
321
322                        $ldap = $GLOBALS['phpgw']->common->ldapConnect($external_srcs[$id_source]['host'], $external_srcs[$id_source]['acc'],$external_srcs[$id_source]['pw'], false);
323                        if (!$ldap)
324                        {
325                                return false;
326                        }
327
328                        // Option recursive commented out
329                        /*
330                        if ($recursive)
331                        {
332                                $tree = $this->get_ldap_tree_recursive($ldap, $context, $this->srcs[$id_source]['obj'],$this->srcs[$id_source]['branch']);
333                                $tree['recursive'] = true;
334
335                                return $tree;
336                        }
337                        */
338
339                        return $this->get_ldap_tree_level($id_source, $ldap, $context, $external_srcs[$id_source]['obj'],$external_srcs[$id_source]['branch'], 1);
340                }
341
[2]342                /*!
343
344                        THIS FUNCTION IS NOT TESTED AND IS PROBABLY BROKEN!
345                        I WILL CORRECT IT IN THE NEAR FUTURE
346
347                */
348                function get_ldap_tree_recursive($resource, $context, $objectClass)
349                {
350                        $filter = '(!(objectClass='.$objectClass.'))';
351                        $result_res = ldap_list($resource, $context, $filter);
352
353                        if ($result_res === false)
354                        {
355                                return null;
356                        }
[285]357                       
[2]358                        $count = ldap_count_entries($resource,$result_res);
359                        if ( $count == 0 )
360                        {
361                                $filter = 'objectClass='.$objectClass;
362                                $result_res2 = ldap_list($resource, $context, $filter);
363                                $entries_count = ldap_count_entries($resource, $result_res2);
364
365                                if ($result_res2 !== false && $entries_count > 0)
366                                {
367                                        return $entries_count;
368                                }
369                                else
370                                {
371                                        return null;
372                                }
373                        }
[285]374                       
[2]375                        $entries = ldap_get_entries($resource, $result_res);
[285]376                       
[2]377                        for ($i = 0; $i < $entries['count']; $i++)
378                        {
379                                $subtree = $this->get_ldap_tree_recursive($resource, $entries[$i]['dn'], $objectClass);
[285]380                               
[2]381                                $dn_parts=ldap_explode_dn($entries[$i]['dn'],1);
[285]382                               
383                                if ($subtree !== null and is_array($subtree))
[2]384                                {
385                                        $tree[$i]['name'] = $dn_parts[0];
386                                        $tree[$i]['type'] = 'catalog_group';
387                                        $tree[$i]['recursive'] = true;
388                                        $tree[$i]['sub_branch'] = $subtree;
389                                }
390                                else if (is_int($subtree) and $subtree !== null)
391                                {
392                                        $tree[$i] = array(
393                                                'name'       => $dn_parts[0],
394                                                'type'       => 'catalog',
395                                                'class'      => 'global_contact_manager',
396                                                'icon'       => 'share-mini.png',
397                                                'value'      => $entries[$i]['dn'],
398                                                'sub_branch' => false
399                                        );
[285]400                                }
[2]401                        }
402
403                        if (is_array($tree))
404                        {
405                                return $tree;
406                        }
407                        else
408                        {
409                                return null;
410                        }
411                }
[285]412               
[2]413                function get_ldap_referrals($ds, $dn, $filter) {
[285]414                       
[2]415                        ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);
416                        ldap_set_option($ds,LDAP_OPT_PROTOCOL_VERSION,3);
[285]417                       
[2]418                        if ($ds) {
419                            ldap_bind($ds);
[285]420                                $sr=ldap_list($ds,$dn, $filter);                   
[2]421                                $ref = ldap_first_reference($ds, $sr);
422                                $array_referral = array();
423                                $idx = 0;
[285]424                               
[2]425                                 while ($ref) {
426                                        $array_referral[$idx++] = ldap_get_dn($ds, $ref);
427                                        $ref = ldap_next_reference($ds, $ref);
428                                }
429                                return $array_referral;
430                        }
[285]431                        else
[2]432                                return false;
433                }
434
435                function get_ldap_sub_branches_referrals($ds, $dn, $filter) {
[285]436                       
[2]437                        $referral = $this -> get_ldap_referrals($ds, $dn, $filter);
438                        $sub_branches = array();
[285]439                       
[2]440                        for($i = 0; $i <count($referral); $i++) {
441                                $dn = str_replace("??base","",preg_replace('!^(ldap://[^/]+)/(.*$)!', '\\2', $referral[$i]));
[285]442                                $dn = explode(",",$dn);                         
[2]443                                $dn = strtoupper(str_replace("ou=", "",$dn[0]));
444                                $dn = str_replace("DC=", "",$dn);
[285]445                                                                                                                                                                               
[2]446                                $sub_branch = array(
447                                                                                        'name' => $dn,
448                                                                'type' => 'unknown',
449                                                                'value' => $referral[$i],
[285]450                                                                'sub_branch' => false           
451                                                                                );                                                                                                                     
452                                $sub_branches[$i] = $sub_branch;                       
[2]453                        }
454                        return $sub_branches;
455                }
[285]456               
[2]457
[284]458                function translate_accentuation($text)
[2]459                {
[284]460                        /*
[4500]461                         * Esta operação resolve o problema causado pela conversão de caracteres acentuados realizada
462                         * pela função ldap_explode_dn().
[284]463                         */
464
465                        return utf8_decode(preg_replace("/\\\([0-9A-Fa-f]{2})/e", "''.chr(hexdec('\\1')).''", $text));
466                }
467
468                function get_ldap_tree_level($id_source, $resource, $context, $objectClass, $branch_dn, $external = 0)
469                {
[1600]470
[284]471                        /*
472                         * TODO: Search timeouts
473                         */
[1600]474
475                        $dn_parts = ldap_explode_dn(($refer_context ? $refer_context : $context),1);
[23]476                        //$filter = '(!(objectClass='.$objectClass.'))';
477                        // Don't show OU's whith phpgwAccountVisible equal to '-1'
[284]478                        if ($external)
479                        {
480                                // external source: get all organizationalUnits
481                                $filter = '(objectClass=organizationalUnit)';
482                        }
483                        else
484                        {
485                                // get any objectClass except the objectClass used for the source
486                                // and whose attribute phpgwAccountVisible value is different from -1
487                                $filter = '(&(!(objectClass='.$objectClass.')) (!(phpgwAccountVisible=-1)))';
488                        }
[4352]489                        $result_res = @ldap_list($resource,  $context, $filter, array(), 0, 0);
[1600]490                        @ldap_sort($resource, $result_res, 'ou');
491
492                        // Timeouts commented out
493                        /*
494                        if ($result_res === false)
495                        {
[2]496                                return null;
[1600]497                        }
498                        */
499
[2]500                        $count = ldap_count_entries($resource,$result_res);
[1600]501
[2]502                        if ( $count == 0 )
503                        {
[284]504                                $filter = '(objectClass='.$objectClass.')';
505                                // Get only one attribute of the source's objectClass
[4352]506                                $result_res2 = @ldap_list($resource, $context, $filter, Array('cn'), 0, 1);
[2]507                                $entries_count = ldap_count_entries($resource, $result_res2);
508
509                                if ($result_res2 !== false && $entries_count > 0)
510                                {
511                                        return array(
[284]512                                                'name'       => $this->translate_accentuation($dn_parts[0]),
[2]513                                                'type'       => 'catalog',
514                                                'class'      => 'bo_global_ldap_catalog',
[284]515                                                // Pass the variable $external as a parameter to the constructor
516                                                'class_args' => array($id_source, $context, $external),
[2]517                                                'icon'       => 'globalcatalog-mini.png',
518                                                'value'      => $context,
519                                                'sub_branch' => false
520                                        );
521                                }
522                                else
523                                {
524                                        return array(
[284]525                                                'name' => $this->translate_accentuation($dn_parts[0]),
[2]526                                                'type' => 'empty'
527                                        );
528                                }
529                        }
[1600]530
[2]531                        $sub_branch_found = false;
532                        $i = 0;
533                        for ($entry = ldap_first_entry($resource, $result_res);
534                             $entry != false;
535                             $entry = ldap_next_entry($resource, $entry))
536                        {
537                                $dn = ldap_get_dn($resource, $entry);
538                                $dn_parts_1 = ldap_explode_dn($dn,1);
539                                $dn_parts_full = ldap_explode_dn($dn,0);
540                                list($group) = explode('=',$dn_parts_full[0]);
[284]541
[4500]542                                //Faz a comparação do branch como case insensitive
[284]543                                if (strtolower($group) == strtolower($branch_dn) or $branch_dn === 'all')
[2]544                                {
545                                        $tree['sub_branch'][$i] = array(
[284]546                                                'name'  => $this->translate_accentuation($dn_parts_1[0]),
[2]547                                                'type'  => 'unknown',
[4352]548                                                'value' =>  $dn,
[284]549                                                'sub_branch' => false
[2]550                                        );
551                                        $sub_branch_found = true;
552                                }
553                                $i++;
554                        }
[1600]555
556
[2]557                        $filter = 'objectClass='.$objectClass;
[4352]558                        $result_res2 = @ldap_list($resource, $context, $filter, Array('cn'), 0, 1);
[2]559                        $entries_count = ldap_count_entries($resource, $result_res2);
560
561                        if ($result_res2 !== false && $entries_count > 0 && $sub_branch_found)
562                        {
[284]563                                $tree['name']       = $this->translate_accentuation($dn_parts[0]);
[2]564                                $tree['type']       = 'mixed_catalog_group';
565                                $tree['class']      = 'bo_global_ldap_catalog';
[284]566                                // Pass the variable $external as a parameter to the constructor
567                                $tree['class_args'] = array($id_source,$context,$external);
[2]568                                $tree['icon']       = 'globalcatalog-mini.png';
569                                $tree['value']      = $context;
570                        }
571                        elseif ($result_res2 !== false && $entries_count > 0 && !$sub_branch_found)
572                        {
573                                return array(
[284]574                                        'name'       => $this->translate_accentuation($dn_parts[0]),
[2]575                                        'type'       => 'catalog',
576                                        'class'      => 'bo_global_ldap_catalog',
[284]577                                        // Pass the variable $external as a parameter to the constructor
578                                        'class_args' => array($id_source, $context,$external),
[2]579                                        'icon'       => 'globalcatalog-mini.png',
580                                        'value'      => $context,
581                                        'sub_branch' => false
582                                );
583                        }
584                        else
585                        {
[284]586                                $tree['name']       = $this->translate_accentuation($dn_parts[0]);
[2]587                                $tree['type']       = 'catalog_group';
588                                $tree['class']      = 'bo_catalog_group_catalog';
[284]589                                // Pass the variable $external as a parameter to the constructor
590                                $tree['class_args'] = array('$this', '$this->get_branch_by_level($this->catalog_level[0])', $external);
[2]591                                $tree['value']      = $context;
592                                $tree['ldap']       = array('id_source' => $id_source, 'context' => $context);
593                        }
[285]594                       
[2]595                        usort($tree['sub_branch'], array($this, "compareTreeNodes"));
596                        return $tree;
597                }
598
599                function compareTreeNodes($a, $b)       {
[285]600                                               
[2]601                        return strnatcasecmp($a['name'], $b['name']);
[285]602                }       
[2]603
604        }
605?>
Note: See TracBrowser for help on using the repository browser.