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

Revision 285, 18.9 KB checked in by brunocosta, 16 years ago (diff)

Correção dos problemas gerados no commit anterior, a funcionalidade citada no ticket #199 foram temporariamente desativadas.

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