class_config.inc 42.6 KB
Newer Older
1
2
3
4
5
<?php

/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2003-2010  Cajus Pollmeier
6
  Copyright (C) 2011-2015  FusionDirectory
7
8
9
10
11
12
13
14
15
16
17
18
19

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
20
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
21
22
*/

23
24
25
/*!
 * \file class_config.inc
 *  Source code for the class config
26
 */
27

28
/*!
29
 * \brief This class is responsible for parsing and querying the
30
 * fusiondirectory configuration file.
31
32
33
34
35
36
 */

class config  {

  /* XML parser */
  var $parser;
37
38
39
40
41
42
  var $config_found     = FALSE;
  var $tags             = array();
  var $level            = 0;
  var $gpc              = 0;
  var $section          = "";
  var $currentLocation  = "";
43
44
45

  /*!
   * \brief Store configuration for current location
46
   */
47
  var $current = array();
48
49

  /* Link to LDAP-server */
50
51
  var $ldap       = NULL;
  var $referrals  = array();
52

53
  /*
54
   * \brief Configuration data
55
56
   *
   * - $data['SERVERS'] contains server informations.
Benoit Mortier's avatar
Benoit Mortier committed
57
   */
58
59
60
61
62
63
64
65
66
  var $data = array(
    'TABS'      => array(),
    'LOCATIONS' => array(),
    'SERVERS'   => array(),
    'MAIN'      => array(),
    'MENU'      => array()
  );
  var $basedir        = "";
  var $config_version = "NOT SET";
67

Benoit Mortier's avatar
Benoit Mortier committed
68
  /* Keep a copy of the current department list */
69
70
71
72
73
  var $departments      = array();
  var $idepartments     = array();
  var $department_info  = array();
  var $filename         = "";
  var $last_modified    = 0;
74

Benoit Mortier's avatar
Benoit Mortier committed
75

76
77
  /*!
   * \brief Class constructor of the config class
78
   *
79
   * \param string $filename path to the configuration file
80
   *
81
   * \param string $basedir base directory
Benoit Mortier's avatar
Benoit Mortier committed
82
   */
83
  function __construct($filename, $basedir = "")
84
  {
85
    $this->basedir  = $basedir;
86
87

    /* Parse config file directly? */
88
    if ($filename != "") {
89
90
91
92
93
      $this->parse($filename);
    }
  }


94
95
  /*!
   * \brief Check and reload the configuration
96
   *
97
98
99
   * This function checks if the configuration has changed, since it was
   * read the last time and reloads it. It uses the file mtime to check
   * weither the file changed or not.
100
   */
101
  function check_and_reload($force = FALSE)
102
  {
103
    /* Check if class_location.inc has changed, this is the case
104
        if we have installed or removed plugins. */
105
    $tmp = stat(CACHE_DIR."/".CLASS_CACHE);
106
107
    if (session::global_is_set("class_location.inc:timestamp")) {
      if ($tmp['mtime'] != session::global_get("class_location.inc:timestamp")) {
108
109
110
        session::global_un_set("plist");
      }
    }
111
    session::global_set("class_location.inc:timestamp", $tmp['mtime']);
112

113
    if (($this->filename != "") && ((filemtime($this->filename) != $this->last_modified) || $force)) {
114

115
116
117
118
119
120
      $this->config_found     = FALSE;
      $this->tags             = array();
      $this->level            = 0;
      $this->gpc              = 0;
      $this->section          = "";
      $this->currentLocation  = "";
121
122
123
124

      $this->parse($this->filename);
      $this->set_current($this->current['NAME']);
    }
125
  }
126
127


128
129
  /*!
   * \brief Parse the given configuration file
130
   *
131
132
   * Parses the configuration file and displays errors if there
   * is something wrong with it.
133
   *
134
   * \param string $filename The filename of the configuration file.
Benoit Mortier's avatar
Benoit Mortier committed
135
   */
136
  function parse($filename)
137
138
139
140
141
142
143
144
145
146
  {
    $this->last_modified  = filemtime($filename);
    $this->filename       = $filename;
    $fh       = fopen($filename, "r");
    $xmldata  = fread($fh, 100000);
    fclose($fh);
    $this->parse_data($xmldata);
  }

  function parse_data ($xmldata)
147
148
  {
    $this->data = array(
149
150
151
152
153
154
      "TABS"      => array(),
      "LOCATIONS" => array(),
      "MAIN"      => array(),
      "MENU"      => array()
    );

155
156
157
158
    $this->parser = xml_parser_create();
    xml_set_object($this->parser, $this);
    xml_set_element_handler($this->parser, "tag_open", "tag_close");

159
    if (!xml_parse($this->parser, chop($xmldata))) {
160
      $msg = sprintf(_("XML error in fusiondirectory.conf: %s at line %d"),
161
162
163
164
165
            xml_error_string(xml_get_error_code($this->parser)),
            xml_get_current_line_number($this->parser));
      msg_dialog::display(_("Configuration error"), $msg, FATAL_ERROR_DIALOG);
      exit;
    }
166
    xml_parser_free($this->parser);
167
168
  }

Benoit Mortier's avatar
Benoit Mortier committed
169

170
  /*!
171
   * \brief Open xml tag when parsing the xml config
Benoit Mortier's avatar
Benoit Mortier committed
172
   *
173
   * \param string $parser
174
   *
175
   * \param string $tag
176
   *
177
   * \param string $attrs
Benoit Mortier's avatar
Benoit Mortier committed
178
   */
179
180
181
  function tag_open($parser, $tag, $attrs)
  {
    /* Save last and current tag for reference */
182
    $this->tags[$this->level] = $tag;
183
184
185
    $this->level++;

    /* Trigger on CONF section */
186
187
188
    if ($tag == 'CONF') {
      $this->config_found = TRUE;
      if (isset($attrs['CONFIGVERSION'])) {
189
190
191
192
193
        $this->config_version = $attrs['CONFIGVERSION'];
      }
    }

    /* Return if we're not in config section */
194
    if (!$this->config_found) {
195
196
197
198
      return;
    }

    /* yes/no to true/false and upper case TRUE to true and so on*/
199
200
201
    foreach ($attrs as $name => $value) {
      if (preg_match("/^(true|yes)$/i", $value)) {
        $attrs[$name] = "TRUE";
202
      } elseif (preg_match("/^(false|no)$/i", $value)) {
203
        $attrs[$name] = "FALSE";
204
      }
205
206
207
    }

    /* Look through attributes */
208
    switch ($this->tags[$this->level - 1]) {
209
210

      /* Handle tab section */
211
212
      case 'TAB':
        $name = $this->tags[$this->level - 2];
213

214
215
216
217
        /* Create new array? */
        if (!isset($this->data['TABS'][$name])) {
          $this->data['TABS'][$name] = array();
        }
218

219
220
221
        /* Add elements */
        $this->data['TABS'][$name][] = $attrs;
        break;
222

223
      /* Handle location */
224
      case 'LOCATION':
225
226
227
228
229
230
231
232
233
234
235
236
237
        if ($this->tags[$this->level - 2] == 'MAIN') {
          $name           = $attrs['NAME'];
          $name           = preg_replace("/[<>\"']/", "", $name);
          $attrs['NAME']  = $name;

          $this->currentLocation = $name;

          /* Add location elements */
          $this->data['LOCATIONS'][$name] = $attrs;
        }
        break;

      /* Handle referral tags */
238
      case 'REFERRAL':
239
240
241
        if ($this->tags[$this->level - 2] == 'LOCATION') {
          $url    = $attrs['URI'];
          $server = preg_replace('!^([^:]+://[^/]+)/.*$!', '\\1', $url);
242

243
244
245
246
          /* Add location elements */
          if (!isset($this->data['LOCATIONS'][$this->currentLocation]['REFERRAL'])) {
            $this->data['LOCATIONS'][$this->currentLocation]['REFERRAL'] = array();
          }
247

248
249
250
          $this->data['LOCATIONS'][$this->currentLocation]['REFERRAL'][$server] = $attrs;
        }
        break;
251

252
      /* Load main parameters */
253
      case 'MAIN':
254
255
        $this->data['MAIN'] = array_merge ($this->data['MAIN'], $attrs);
        break;
256
257
258
    }
  }

Benoit Mortier's avatar
Benoit Mortier committed
259

260
  /*!
261
   * \brief Close xml tag when parsing the xml config
Benoit Mortier's avatar
Benoit Mortier committed
262
   *
263
   * \param string $parser
264
   *
265
   * \param string $tag
Benoit Mortier's avatar
Benoit Mortier committed
266
   */
267
268
269
  function tag_close($parser, $tag)
  {
    /* Close config section */
270
271
    if ($tag == 'CONF') {
      $this->config_found = FALSE;
272
273
274
275
276
    }
    $this->level--;
  }


277
  /*!
278
   * \brief Get the password when needed from the config file
Benoit Mortier's avatar
Benoit Mortier committed
279
   *
280
   * This function can be used to get the password associated to
Benoit Mortier's avatar
Benoit Mortier committed
281
   * a keyword in the config file
282
   *
283
   * \param string $creds the keyword associated to the password needed
Benoit Mortier's avatar
Benoit Mortier committed
284
285
286
   *
   * \return string the password corresponding to the keyword
   */
287
288
  function get_credentials($creds)
  {
289
290
291
    if (isset($_SERVER['HTTP_FDKEY'])) {
      if (!session::global_is_set('HTTP_FDKEY_CACHE')) {
        session::global_set('HTTP_FDKEY_CACHE', array());
292
      }
293
      $cache = session::global_get('HTTP_FDKEY_CACHE');
294
      if (!isset($cache[$creds])) {
295
        try {
296
297
          $cache[$creds] = cred_decrypt($creds, $_SERVER['HTTP_FDKEY']);
          session::global_set('HTTP_FDKEY_CACHE', $cache);
298
299
300
301
302
303
304
305
        } catch (Exception $e) {
          $msg = sprintf(
            _('It seems you are trying to decode something which is not encoded : %s<br/>\n'.
              'Please check you are not using a fusiondirectory.secrets file while your passwords are not encrypted.'),
            $e->getMessage()
          );
          msg_dialog::display(_("Configuration error"), $msg, FATAL_ERROR_DIALOG);
        }
306
      }
307
      return $cache[$creds];
308
    }
309
    return $creds;
310
311
312
  }


313
  /*!
314
   * \brief Get a LDAP link object
315
316
317
318
319
320
321
322
323
324
   *
   * This function can be used to get an ldap object, which in turn can
   * be used to query the LDAP. See the LDAP class for more information
   * on how to use it.
   *
   * Example usage:
   * \code
   * $ldap = $this->config->get_ldap_link();
   * \endcode
   *
325
   * \param boolean $sizelimit Weither to impose a sizelimit on the LDAP object or not.
326
327
   * Defaults to false. If set to true, the size limit in the configuration
   * file will be used to set the option LDAP_OPT_SIZELIMIT.
328
   *
329
330
   * \return ldapMultiplexer object
   */
331
  function get_ldap_link($sizelimit = FALSE)
332
  {
333
    if ($this->ldap === NULL || !is_resource($this->ldap->cid)) {
334
335

      /* Build new connection */
336
      $this->ldap = ldap_init ($this->current['SERVER'], $this->current['BASE'],
337
338
339
          $this->current['ADMINDN'], $this->get_credentials($this->current['ADMINPASSWORD']));

      /* Check for connection */
340
      if (is_null($this->ldap) || (is_int($this->ldap) && $this->ldap == 0)) {
341
342
343
344
345
        msg_dialog::display(_("LDAP error"), _("Cannot bind to LDAP. Please contact the system administrator."), FATAL_ERROR_DIALOG);
        exit();
      }

      /* Move referrals */
346
347
      if (!isset($this->current['REFERRAL'])) {
        $this->ldap->referrals = array();
348
      } else {
349
        $this->ldap->referrals = $this->current['REFERRAL'];
350
351
      }

352
      if (!session::global_is_set('size_limit')) {
353
354
        session::global_set('size_limit',   $this->current['LDAPSIZELIMIT']);
        session::global_set('size_ignore',  preg_match('/true/i', $this->current['LDAPSIZEIGNORE']));
355
356
357
358
      }
    }

    $obj  = new ldapMultiplexer($this->ldap);
359
    if ($sizelimit) {
360
361
362
363
      $obj->set_size_limit(session::global_get('size_limit'));
    } else {
      $obj->set_size_limit(0);
    }
364
    return $obj;
365
366
  }

Benoit Mortier's avatar
Benoit Mortier committed
367

368
  /*!
369
   * \brief Set the current location
370
   *
371
   * \param string $name the name of the location
372
373
374
   */
  function set_current($name)
  {
375
    $this->current = $this->data['LOCATIONS'][$name];
376

377
378
    if (isset($this->current['INITIAL_BASE'])) {
      session::global_set('CurrentMainBase', $this->current['INITIAL_BASE']);
379
380
381
    }

    /* Sort referrals, if present */
382
383
384
385
386
387
388
389
390
    if (isset($this->current['REFERRAL'])) {
      $bases    = array();
      $servers  = array();
      foreach ($this->current['REFERRAL'] as $ref) {
        $server = preg_replace('%^(.*://[^/]+)/.*$%', '\\1', $ref['URI']);
        $base   = preg_replace('%^.*://[^/]+/(.*)$%', '\\1', $ref['URI']);

        $bases[$base]   = strlen($base);
        $servers[$base] = $server;
391
392
393
394
395
396
      }
      asort($bases);
      reset($bases);
    }

    /* SERVER not defined? Load the one with the shortest base */
397
398
    if (!isset($this->current['SERVER'])) {
      $this->current['SERVER'] = $servers[key($bases)];
399
400
401
    }

    /* BASE not defined? Load the one with the shortest base */
402
403
    if (!isset($this->current['BASE'])) {
      $this->current['BASE'] = key($bases);
404
405
406
    }

    /* Convert BASE to have escaped special characters */
407
    $this->current['BASE'] = @LDAP::convert($this->current['BASE']);
408
409

    /* Parse LDAP referral informations */
410
411
412
413
414
415
416
417
418
419
420
421
422
423
    if (!isset($this->current['ADMINDN']) || !isset($this->current['ADMINPASSWORD'])) {
      $url      = $this->current['SERVER'];
      $referral = $this->current['REFERRAL'][$url];

      $this->current['ADMINDN']       = $referral['ADMINDN'];
      $this->current['ADMINPASSWORD'] = $referral['ADMINPASSWORD'];
    }

    /* We need LDAPSIZELIMIT and LDAPSIZEIGNORE set before we connect to the ldap */
    if (!isset($this->current['LDAPSIZELIMIT'])) {
      $this->current['LDAPSIZELIMIT'] = 200;
    }
    if (!isset($this->current['LDAPSIZEIGNORE'])) {
      $this->current['LDAPSIZEIGNORE'] = "TRUE";
424
425
    }

426
427
428
    /* Load in-ldap configuration */
    $this->load_inldap_config();

429
430
431
432
433
    /* Remove possibly added ',' from end of group and people ou */
    $this->current['GROUPRDN']  = preg_replace("/,*$/", "", $this->current['GROUPRDN']);
    $this->current['USERRDN']   = preg_replace("/,*$/", "", $this->current['USERRDN']);

    /* We update LDAPSIZELIMIT as it may have been changed by ldap config */
434
    session::global_set('size_limit', $this->current['LDAPSIZELIMIT']);
435

436
437
438
439
    if (class_available('systemManagement')) {
      /* Load server informations */
      $this->load_servers();
    }
440
441
442
443
444
445
446
447
448

    $debugLevel = $this->get_cfg_value('DEBUGLEVEL');
    if ($debugLevel & DEBUG_CONFIG) { // value from LDAP can't activate DEBUG_CONFIG
      $debugLevel -= DEBUG_CONFIG;
    }
    if (isset($this->data['MAIN']['DEBUGLEVEL'])) {
      $debugLevel |= $this->data['MAIN']['DEBUGLEVEL'];
    }
    session::global_set('DEBUGLEVEL', $debugLevel);
449
450

    IconTheme::loadThemes('themes');
451
452

    timezone::setDefaultTimezoneFromConfig();
453
454
455
  }


456
457
  /*!
   * \brief Load server information from config/LDAP
458
   *
459
460
461
   * This function searches the LDAP for servers (e.g. goImapServer, goMailServer etc.)
   * and stores information about them $this->data['SERVERS']. In the case of mailservers
   * the main section of the configuration file is searched, too.
462
463
464
465
   */
  function load_servers ()
  {
    /* Only perform actions if current is set */
466
    if ($this->current === NULL) {
467
468
469
470
      return;
    }

    /* Fill imap servers */
471
    $ldap = $this->get_ldap_link();
472
473
    $ldap->cd ($this->current['BASE']);

474
    /* Search mailMethod configuration in main section too */
475
    $this->current['MAILMETHOD']    = $this->get_cfg_value("mailMethod", "");
476
    $mailMethodClass                = 'mailMethod'.$this->current['MAILMETHOD'];
477
478
    if (class_available($mailMethodClass)) {
      $this->data['SERVERS']['IMAP']  = $mailMethodClass::get_server_list($this);
479
    } elseif (class_available('mailMethod')) {
480
481
482
483
484
485
      msg_dialog::display(
        _("Error"),
        sprintf(_("The selected mail method (class %s) is not available"), $mailMethodClass),
        ERROR_DIALOG
      );
    }
486

487
488
489
490
491
492
493
494
495
496
    /* Get kerberos servers */
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goKrbServer)(goKrbRealm=*)(goKrbAdmin=*))");
    $this->data['SERVERS']['KERBEROS'] = array();
    while ($attrs = $ldap->fetch()) {
      $this->data['SERVERS']['KERBEROS'][] = array(
        'SERVER'  => $attrs['cn'][0],
        'REALM'   => $attrs['goKrbRealm'][0],
        'ADMIN'   => $attrs['goKrbAdmin'][0]
      );
497
498
    }

499
500
501
502
    /* Get cups servers */
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goCupsServer)");
    $this->data['SERVERS']['CUPS'] = array();
503
    while ($attrs = $ldap->fetch()) {
504
      $this->data['SERVERS']['CUPS'][] = $attrs['cn'][0];
505
506
    }

507
508
509
510
511
512
513
514
515
516
    /* Get fax servers */
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goFaxServer)");
    $this->data['SERVERS']['FAX'] = array();
    while ($attrs = $ldap->fetch()) {
      $this->data['SERVERS']['FAX'][] = array(
        'SERVER'    => $attrs['cn'][0],
        'LOGIN'     => $attrs['goFaxAdmin'][0],
        'PASSWORD'  => $attrs['goFaxPassword'][0]
      );
517
518
519
    }

    /* Get asterisk servers */
520
521
522
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goFonServer)");
    $this->data['SERVERS']['FON'] = array();
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
    while ($attrs = $ldap->fetch()) {

      $entry = array(
        'DN'                  => $attrs['dn'],
        'SERVER'              => $attrs['cn'][0],
        'LOGIN'               => $attrs['goFonAdmin'][0],
        'PASSWORD'            => $attrs['goFonPassword'][0],
        'DB'                  => "gophone",
        'SIP_TABLE'           => "sip_users",
        'EXT_TABLE'           => "extensions",
        'VOICE_TABLE'         => "voicemail_users",
        'QUEUE_TABLE'         => "queues",
        'QUEUE_MEMBER_TABLE'  => "queue_members"
      );
      if (isset($attrs['fdAsteriskDriver'][0])) {
        $entry['DRIVER'] = $attrs['fdAsteriskDriver'][0];
      }
540
541

      /* Add 0 entry for development */
542
543
      if (count($this->data['SERVERS']['FON']) == 0) {
        $this->data['SERVERS']['FON'][0] = $entry;
544
      }
545
546

      /* Add entry with 'dn' as index */
547
      $this->data['SERVERS']['FON'][$attrs['dn']] = $entry;
548
549
550
    }

    /* Get logdb server */
551
552
553
554
555
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goLogDBServer)");
    if ($ldap->count()) {
      $attrs = $ldap->fetch();
      if (!isset($attrs['gosaLogDB'][0])) {
556
557
        $attrs['gosaLogDB'][0] = "gomon";
      }
558
559
560
561
562
563
      $this->data['SERVERS']['LOG'] = array(
        'SERVER'    => $attrs['cn'][0],
        'LOGIN'     => $attrs['goLogAdmin'][0],
        'DB'        => $attrs['gosaLogDB'][0],
        'PASSWORD'  => $attrs['goLogPassword'][0]
      );
564
565
566
    }

    /* Get NFS server lists */
567
568
569
570
571
572
573
574
575
    $tmp  = array("default");
    $tmp2 = array("default");
    $ldap->cd($this->current['BASE']);
    $ldap->search("(&(objectClass=goShareServer)(goExportEntry=*))");
    while ($attrs = $ldap->fetch()) {
      for ($i = 0; $i < $attrs["goExportEntry"]["count"]; $i++) {
        if (preg_match('/^[^|]+\|[^|]+\|NFS\|.*$/', $attrs["goExportEntry"][$i])) {
          $path   = preg_replace ("/^[^|]+\|[^|]+\|[^|]+\|[^|]+\|([^|]+).*$/", '\1', $attrs["goExportEntry"][$i]);
          $tmp[]  = $attrs["cn"][0].":$path";
576
        }
577
578
579
        if (preg_match('/^[^|]+\|[^|]+\|NBD\|.*$/', $attrs["goExportEntry"][$i])) {
          $path   = preg_replace ("/^[^|]+\|[^|]+\|[^|]+\|[^|]+\|([^|]+).*$/", '\1', $attrs["goExportEntry"][$i]);
          $tmp2[] = $attrs["cn"][0].":$path";
580
        }
581
582
      }
    }
583
584
    $this->data['SERVERS']['NFS'] = $tmp;
    $this->data['SERVERS']['NBD'] = $tmp2;
585
586
587

    /* Load Terminalservers */
    $ldap->cd ($this->current['BASE']);
588
589
590
591
    $ldap->search ("(objectClass=goTerminalServer)", array("cn","gotoSessionType"));
    $this->data['SERVERS']['TERMINAL']                = array();
    $this->data['SERVERS']['TERMINAL'][]              = "default";
    $this->data['SERVERS']['TERMINAL_SESSION_TYPES']  = array();
592

593
594
595
596
    while ($attrs = $ldap->fetch()) {
      $this->data['SERVERS']['TERMINAL'][] = $attrs["cn"][0];
      if (isset( $attrs["gotoSessionType"]['count'])) {
        for ($i = 0; $i < $attrs["gotoSessionType"]['count']; $i++) {
597
          $this->data['SERVERS']['TERMINAL_SESSION_TYPES'][$attrs["cn"][0]][] = $attrs["gotoSessionType"][$i];
598
599
600
601
        }
      }
    }

602
    /* Ldap Server
603
     */
604
605
606
607
    $this->data['SERVERS']['LDAP'] = array();
    $ldap->cd($this->current['BASE']);
    $ldap->search("(&(objectClass=goLdapServer)(goLdapBase=*))");
    while ($attrs = $ldap->fetch()) {
608
609
610
611
      $this->data['SERVERS']['LDAP'][$attrs['dn']] = $attrs;
    }

    /* Get misc server lists */
612
613
614
615
616
617
    $this->data['SERVERS']['SYSLOG']  = array("default");
    $this->data['SERVERS']['NTP']     = array("default");
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goNtpServer)");
    while ($attrs = $ldap->fetch()) {
      $this->data['SERVERS']['NTP'][] = $attrs["cn"][0];
618
    }
619
620
621
622
    $ldap->cd($this->current['BASE']);
    $ldap->search("(objectClass=goSyslogServer)");
    while ($attrs = $ldap->fetch()) {
      $this->data['SERVERS']['SYSLOG'][] = $attrs["cn"][0];
623
624
    }

Benoit Mortier's avatar
Benoit Mortier committed
625
    /* Get samba servers from LDAP */
626
    $this->data['SERVERS']['SAMBA'] = array();
627
    if (class_available('sambaAccount')) {
628
629
630
631
632
633
      $ldap->cd($this->current['BASE']);
      $ldap->search("(objectClass=sambaDomain)");
      while ($attrs = $ldap->fetch()) {
        $this->data['SERVERS']['SAMBA'][$attrs['sambaDomainName'][0]] = array( "SID" => "","RIDBASE" => "");
        if (isset($attrs["sambaSID"][0])) {
          $this->data['SERVERS']['SAMBA'][$attrs['sambaDomainName'][0]]["SID"] = $attrs["sambaSID"][0];
634
        }
635
        if (isset($attrs["sambaAlgorithmicRidBase"][0])) {
636
637
          $this->data['SERVERS']['SAMBA'][$attrs['sambaDomainName'][0]]["RIDBASE"] = $attrs["sambaAlgorithmicRidBase"][0];
        }
638
639
      }

640
641
642
643
644
      /* If no samba servers are found, look for configured sid/ridbase */
      if (count($this->data['SERVERS']['SAMBA']) == 0) {
        if (!isset($this->current["SAMBASID"]) || !isset($this->current["SAMBARIDBASE"])) {
          msg_dialog::display(_("Configuration error"), _("sambaSID and/or sambaRidBase missing in the configuration!"), ERROR_DIALOG);
        } else {
645
          $this->data['SERVERS']['SAMBA']['DEFAULT'] = array(
646
647
648
              "SID" => $this->current["SAMBASID"],
              "RIDBASE" => $this->current["SAMBARIDBASE"]);
        }
649
650
      }
    }
651

652
653
  }

654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  /* Check that configuration is in LDAP, check that no plugin got installed since last configuration update */
  function checkLdapConfig ()
  {
    global $ui;
    $ldap   = $this->get_ldap_link();
    $dn     = CONFIGRDN.$this->current['BASE'];
    $reload = TRUE;
    $ldap->cat($dn, array('fusionConfigMd5'));
    if ($attrs = $ldap->fetch()) {
      if (isset($attrs['fusionConfigMd5'][0]) && ($attrs['fusionConfigMd5'][0] == md5_file(CACHE_DIR."/".CLASS_CACHE))) {
        $reload = FALSE;
      }
    }
    if ($reload) {
      add_lock($dn, $ui->dn);
      $config_plugin = new tabs_configInLdap($this, $this->data['TABS']['CONFIGURATIONTABS'], $dn, 'configuration');
      $config_plugin->save_object();
      $config_plugin->save();
      del_lock($dn);
    }
  }

676
677
678
  function load_inldap_config()
  {
    $ldap = $this->get_ldap_link();
679
    $ldap->cat(CONFIGRDN.$this->current['BASE']);
680
681
682
    if ($attrs = $ldap->fetch()) {
      for ($i = 0; $i < $attrs['count']; $i++) {
        $key = $attrs[$i];
683
        if (preg_match('/^fdTabHook$/i', $key)) {
684
          for ($j = 0; $j < $attrs[$key]['count']; ++$j) {
685
            $parts  = explode('|', $attrs[$key][$j], 3);
686
687
688
689
690
691
692
693
            $class  = strtoupper($parts[0]);
            $mode   = strtoupper($parts[1]);
            $cmd    = $parts[2];
            if (!isset($this->data['HOOKS'][$class])) {
              $this->data['HOOKS'][$class] = array('CLASS' => $parts[0]);
            }
            $this->data['HOOKS'][$class][$mode] = $cmd;
          }
694
        } elseif (preg_match('/^fd/', $key)) {
695
          if (isset($attrs[$key]['count']) && ($attrs[$key]['count'] > 1)) {
696
697
            $value = $attrs[$key];
            unset($value['count']);
698
699
700
          } else {
            $value = $attrs[$key][0];
          }
701
          $key = strtoupper(preg_replace('/^fd/', '', $key));
702
703
704
705
706
707
          $this->current[$key] = $value;
        }
      }
    }
  }

708

709
  /*!
710
   * \brief Store the departments from ldap in $this->departments
Benoit Mortier's avatar
Benoit Mortier committed
711
   *
712
   * \param string $ignore_dn dn of the department
Benoit Mortier's avatar
Benoit Mortier committed
713
   */
714
  function get_departments($ignore_dn = "")
715
716
  {
    /* Initialize result hash */
717
718
719
    $result = array();

    $result['/'] = $this->current['BASE'];
720
721

    /* Get all department types from department Management, to be able detect the department type.
722
        -It is possible that different department types have the same name,
723
724
         in this case we have to mark the department name to be able to differentiate.
          (e.g l=Name  or   o=Name)
725
     */
726
    $types = departmentManagement::getDepartmentTypes();
727

728
    /* Create a list of attributes to fetch */
729
    $filter       = "";
730
    $ldap_values  = array("objectClass", "description");
731
    foreach ($types as $type) {
732
733
734
      $i = objects::infos($type);
      $filter         .= $i['filter'];
      $ldap_values[]  = $i['mainAttr']; // Specific key for departement objectTypes
735
    }
736
    $filter = "(|".$filter.")";
737
738

    /* Get list of department objects */
739
    $ldap = $this->get_ldap_link();
740
741
    $ldap->cd ($this->current['BASE']);
    $ldap->search ($filter, $ldap_values);
742
    while ($attrs = $ldap->fetch()) {
743
744

      /* Detect department type */
745
746
747
748
      $oc = NULL;
      foreach ($types as $type) {
        if (objects::isOfType($attrs, $type)) {
          $oc = $type;
749
750
751
752
753
          break;
        }
      }

      /* Unknown department type -> skip */
754
      if ($oc == NULL) {
755
756
        continue;
      }
757

758
      $dn   = $ldap->getDN();
759
760
761
762
      $data = objects::infos($oc);
      $this->department_info[$dn] = array("img"         => $data['icon'],
                                         "description"  => isset($attrs['description'][0])?$attrs['description'][0]:"",
                                         "name"         => $attrs[$data['mainAttr']][0]);
763

764
      if ($dn == $ignore_dn) {
765
766
        continue;
      }
767
      $c_dn = convert_department_dn($dn)." (".$data['mainAttr'].")";
768
769

      /* Only assign non-root departments */
770
771
      if ($dn != $result['/']) {
        $result[$c_dn] = $dn;
772
773
774
      }
    }

775
    $this->departments = $result;
776
777
  }

778
  function make_idepartments($max_size = 28)
779
  {
780
    $base   = $this->current['BASE'];
781
    $qbase  = preg_quote($base, '/');
782

783
    $arr  = array();
784

785
    $this->idepartments = array();
786
787

    /* Create multidimensional array, with all departments. */
788
    foreach ($this->departments as $key => $val) {
789
790

      /* Split dn into single department pieces */
791
      $elements = array_reverse(explode(',', preg_replace("/$qbase$/", '', $val)));
792
793
794

      /* Add last ou element of current dn to our array */
      $last = &$arr;
795
      foreach ($elements as $key => $ele) {
796
797

        /* skip empty */
798
799
800
        if (empty($ele)) {
          continue;
        }
801

802
        /* Extract department name */
803
804
805
        $elestr = trim(preg_replace('/^[^=]*+=/', '', $ele), ',');
        $nameA  = trim(preg_replace('/=.*$/', '', $ele), ',');
        if ($nameA != 'ou') {
806
          $nameA = " ($nameA)";
807
        } else {
808
809
          $nameA = '';
        }
810
811

        /* Add to array */
812
        if ($key == (count($elements) - 1)) {
813
814
815
816
817
818
819
820
821
          $last[$elestr.$nameA]['ENTRY'] = $val;
        }

        /* Set next array appending position */
        $last = &$last[$elestr.$nameA]['SUB'];
      }
    }

    /* Add base entry */
822
    $ret['/']['ENTRY']  = $base;
823
824
    $ret['/']['SUB']    = $arr;
    $this->idepartments = $this->generateDepartmentArray($ret, -1, $max_size);
825
826
827
  }


828
829
830
  /*
   * \brief Creates display friendly output from make_idepartments
   *
831
   * \param $arr arr
832
   *
833
   * \param int $depth initialized at -1
834
   *
835
836
   * \param int $max_size initialized at 256
   */
837
  function generateDepartmentArray($arr, $depth = -1, $max_size = 256)
838
839
  {
    $ret = array();
840
    $depth++;
841

842
    /* Walk through array */
843
    ksort($arr);
844
    foreach ($arr as $name => $entries) {
845

846
      /* If this department is the last in the current tree position
847
       * remove it, to avoid generating output for it */
848
      if (count($entries['SUB']) == 0) {
849
850
851
852
        unset($entries['SUB']);
      }

      /* Fix name, if it contains a replace tag */
853
      $name = preg_replace('/\\\\,/', ',', LDAP::fix($name));
854
855

      /* Check if current name is too long, then cut it */
856
857
      if (mb_strlen($name, 'UTF-8') > $max_size) {
        $name = mb_substr($name, 0, ($max_size - 3), 'UTF-8')." ...";
858
859
      }

860
      /* Append the name to the list */
861
      if (isset($entries['ENTRY'])) {
862
        $a = "";
863
864
        for ($i = 0; $i < $depth; $i++) {
          $a .= ".";
865
        }
866
        $ret[$entries['ENTRY']] = $a."&nbsp;".$name;
867
      }
868
869

      /* recursive add of subdepartments */
870
871
      if (isset($entries['SUB'])) {
        $ret = array_merge($ret, $this->generateDepartmentArray($entries['SUB'], $depth, $max_size));
872
873
874
      }
    }

875
    return $ret;
876
877
  }

878
  /*!
879
   * \brief Check if there's the specified bool value set in the configuration
880
881
882
883
884
885
886
887
888
889
890
891
   *
   *  The function checks, weither the specified bool value is set to a true
   *  value in the configuration file. Considered true are either true or yes,
   *  case-insensitive.
   *
   *  Example usage:
   *  \code
   *  if ($this->config->boolValueIsTrue("main", "copyPaste")) {
   *    echo "Copy Paste Handling is enabled";
   *  }
   *  \endcode
   *
892
   *  \param string $section Section in the configuration file.
893
   *
894
   *  \param string $value Key in the given section, which is subject to check
895
   *
Benoit Mortier's avatar
Benoit Mortier committed
896
   *  \return bool TRUE if option set in the config file
Benoit Mortier's avatar
Benoit Mortier committed
897
   */
898
899
  function boolValueIsTrue($section, $value)
  {
900
901
902
    $section  = strtoupper($section);
    $value    = strtoupper($value);
    if (isset($this->data[$section][$value])) {
903

904
905
      $data = $this->data[$section][$value];
      if (preg_match("/^true$/i", $data) || preg_match("/yes/i", $data)) {
906
907
908
909
910
911
912
913
914
915
916
        return TRUE;
      }

    }

    return FALSE;
  }


  function __search(&$arr, $name, $return)
  {
917
918
919
920
921
    $return = strtoupper($return);
    if (is_array($arr)) {
      foreach ($arr as &$a) {
        if (isset($a['CLASS']) && strcasecmp($name, $a['CLASS']) == 0) {
          return (isset($a[$return])?$a[$return]:"");
922
        } else {
923
          $res = $this->__search ($a, $name, $return);
924
          if ($res != "") {
925
926
927
928
            return $res;
          }
        }
      }
929
      unset($a);
930
    }
931
    return "";
932
933
934
  }


935
  /*!
936
   * \brief Search for a configuration setting in different categories
937
938
939
940
941
942
943
944
945
946
   *
   *  Searches for the value of a given key in the configuration data.
   *  Optionally the list of categories to search (tabs, main, locations) can
   *  be specified. The first value that matches is returned.
   *
   *  Example usage:
   *  \code
   *  $postcmd = $this->config->search(get_class($this), "POSTCOMMAND", array("menu", "tabs"));
   *  \endcode
   *
947
   *  \param string $class The class name
948
   *
949
   *  \param string $value Key to search in the configuration data
950
951
952
   *
   *  \param array $categories Array where the search should run
   *
Benoit Mortier's avatar
Benoit Mortier committed
953
954
   *  \return string the value you asked for or empty
   */
955
  function search($class, $value, $categories = "")
956
  {
957
958
959
960
    if (is_array($categories)) {
      foreach ($categories as $category) {
        $res = $this->__search($this->data[strtoupper($category)], $class, $value);
        if ($res != "") {
961
962
963
964
965
966
967
968
969
          return $res;
        }
      }
    } else {
      if ($categories == "") {
        return $this->__search($this->data, $class, $value);
      } else {
        return $this->__search($this->data[strtoupper($categories)], $class, $value);
      }
970
    }
971

972
    return "";
973
974
975
  }


976
  /*!
977
   * \brief Get a configuration value from the config
978
979
980
981
982
983
984
985
986
   *
   *  This returns a configuration value from the config. It either
   *  uses the data of the current location ($this->current),
   *  if it contains the value (e.g. current['BASE']) or otherwise
   *  uses the data from the main configuration section.
   *
   *  If no value is found and an optional default has been specified,
   *  then the default is returned.
   *
987
   * \param string $name The configuration key (case-insensitive)