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

Revision 4838, 19.3 KB checked in by airton, 13 years ago (diff)

Ticket #2150 - Melhorias nas buscas no catalogo global

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