source: branches/2.2/contactcenter/inc/class.bo_ldap_manager.inc.php @ 3282

Revision 3282, 19.7 KB checked in by eduardoalex, 14 years ago (diff)

Ticket #1251 - Commit principal com adição da melhoria no módulo

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