system/classes/config.class.php
author Tom <websitemaster@cogeco.net>
Thu, 24 May 2012 09:59:37 -0400
branchHEAD
changeset 8708 2bdc00d7a98e
parent 8684 86654bff5054
permissions -rw-r--r--
Added tag geeklog_2_0_0b1 for changeset a7b5f3f50d20
     1 <?php
     2 
     3 /* Reminder: always indent with 4 spaces (no tabs). */
     4 // +---------------------------------------------------------------------------+
     5 // | Geeklog 1.8                                                               |
     6 // +---------------------------------------------------------------------------+
     7 // | config.class.php                                                          |
     8 // |                                                                           |
     9 // | Controls the UI and database for configuration settings                   |
    10 // +---------------------------------------------------------------------------+
    11 // | Copyright (C) 2007-2011 by the following authors:                         |
    12 // |                                                                           |
    13 // | Authors: Aaron Blankstein  - kantai AT gmail DOT com                      |
    14 // |          Akeda Bagus       - admin AT gedex DOT web DOT id                |
    15 // |          Tom Homer         - tomhomer AT gmail DOT com                    |
    16 // +---------------------------------------------------------------------------+
    17 // |                                                                           |
    18 // | This program is free software; you can redistribute it and/or             |
    19 // | modify it under the terms of the GNU General Public License               |
    20 // | as published by the Free Software Foundation; either version 2            |
    21 // | of the License, or (at your option) any later version.                    |
    22 // |                                                                           |
    23 // | This program is distributed in the hope that it will be useful,           |
    24 // | but WITHOUT ANY WARRANTY; without even the implied warranty of            |
    25 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             |
    26 // | GNU General Public License for more details.                              |
    27 // |                                                                           |
    28 // | You should have received a copy of the GNU General Public License         |
    29 // | along with this program; if not, write to the Free Software Foundation,   |
    30 // | Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.           |
    31 // |                                                                           |
    32 // +---------------------------------------------------------------------------+
    33 
    34 class config {
    35     /**
    36      * Path to db-config.php file
    37      * @var string
    38      */
    39     var $dbconfig_file;
    40     
    41     /**
    42      * Array of configurations
    43      * @var array
    44      */
    45     var $config_array;
    46     
    47     /**
    48      * Array of configuration tabs, used by autocomplete
    49      * @var array
    50      */
    51     var $conf_tab_arr;
    52     
    53     /**
    54      * Array of configuration features (security rights)
    55      * @var array
    56      */
    57     var $conf_ft_arr;
    58     
    59     /**
    60      * Array of configuration types
    61      * @var array
    62      */
    63     var $conf_type;
    64     
    65     /**
    66      * Whether support new theme format for the later Geeklog 2.0 or not
    67      * @var boolean
    68      */
    69     var $flag_version_2;
    70     
    71     /**
    72      * List of validation rules. Append entries for validation as 
    73      * ('field_name' => '/^perl_compat_regexp$/') that have to match
    74      * with preg_match(). Use these rules with config::_validates()
    75      *
    76      * @var array
    77      * @access public
    78      */
    79 	var $validate = array();
    80 
    81     /**
    82      * List of validation errors.
    83      *
    84      * @var array
    85      * @access public
    86      */
    87 	var $validationErrors = array();
    88     
    89     /**
    90      * Values that failed validation
    91      * 
    92      * @var array
    93      * @access public
    94      */
    95     var $validationErrorValues = array();
    96     
    97     /**
    98      * Changed values that pass the validation.
    99      * If validationErrors is not empty, changed values should be saved
   100      * for later submission
   101      * 
   102      * @var array
   103      * @access public
   104      */
   105     var $tmpValues = array();
   106     
   107     /**
   108      * Changed configuration array (such as mail settings) that pass the validation.
   109      * If validationErrors is not empty, changed values should be saved
   110      * for later submission
   111      * 
   112      * @var array
   113      * @access public
   114      */
   115     var $changedArray = array();
   116     
   117     /**
   118      * Constructor
   119      */
   120     function __construct()
   121     {
   122         $this->config_array = array();
   123         
   124         $this->conf_tab_arr = null;
   125         $this->conf_ft_arr = null;
   126         $this->conf_type = array();
   127     }
   128 
   129     /**
   130      * This method will return an instance of the config class. If an
   131      * instance with the given group/reference name does not exist, then it
   132      * will create a new one. This function insures    that there is only one
   133      * instance for a given group name.
   134      *
   135      *    @param string group_name This is simply the group name that this
   136      *                             config object will control - for the main gl
   137      *                             settings this is 'Core'
   138      *
   139      *    @return config           The newly created or referenced config object
   140      */
   141     public static function &get_instance()
   142     {
   143         static $instance;
   144 
   145         if (!$instance) {
   146             $instance = new config();
   147         }
   148 
   149         return $instance;
   150     }
   151 
   152     /**
   153      * For PHP 4
   154      */
   155     function config()
   156     {
   157         $this->__construct();
   158     }
   159 
   160     /**
   161      * This method sets the secure configuration file (database related
   162      * settings) for the configuration class to read. This should only need to
   163      * be called for the 'Core' group. It also must be called before
   164      * load_baseconfig()
   165      *
   166      * @param string sf        The filename and path of the secure db settings
   167      */
   168 
   169     function set_configfile($sf)
   170     {
   171         $this->dbconfig_file = $sf;
   172     }
   173 
   174     /**
   175      * This method reads the secure configuration file and loads
   176      * lib-database.php. This needs to be called in the 'Core' group before
   177      * &init_config() can be used. It only needs to be called once
   178      */
   179 
   180     function load_baseconfig()
   181     {
   182         global $_DB, $_TABLES, $_CONF;
   183 
   184         include $this->dbconfig_file;
   185         $this->config_array['Core'] =& $_CONF;
   186 
   187         include_once $_CONF['path_system'] . 'lib-database.php';
   188 
   189         // for backward compatibility
   190         $_CONF['ostype'] = PHP_OS;
   191     }
   192 
   193     /**
   194      * This method initializes the configuration array (i.e. $_CONF) and
   195      * will return a reference to the newly created array. The class keeps
   196      * track of this reference, and the set function will mutate it.
   197      *
   198      * @return array(string => mixed)      This is a reference to the
   199      *                                     config array
   200      */
   201     function &initConfig()
   202     {
   203         global $_TABLES;
   204 
   205         // Figure out tabs first
   206         $sql = "SELECT name, value, group_name, type, subgroup, tab FROM {$_TABLES['conf_values']} WHERE 1=1";
   207         $result = DB_query($sql);
   208         $tabs = array();
   209         $curr_group_name = '';
   210         $curr_subgroup = '';
   211         while ($row = DB_fetchArray($result)) {
   212             // For backwards compatibility, add in a tab for plugins that support the old config
   213             if ($row['type'] != 'tab' && $row['tab'] == '' && ($row['group_name'] != $curr_group_name || $row['subgroup'] != $curr_subgroup)) {
   214                 $curr_group_name = $row['group_name'];
   215                 $curr_subgroup = $row['subgroup'];
   216                 $tab_name = 'tab_default_' . $curr_subgroup;
   217                 $tab_id = 0;
   218                 $this->conf_type['tab'][$row[2]][$tab_name] = "config.{$row[2]}.{$tab_name}";
   219                 $this->conf_type['tree'][$row[2]][$row[4]][$tab_name] = "config.{$row[2]}.{$tab_name}";
   220                 
   221                 if (!isset($this->conf_tab_arr[$tab_name])) {
   222                     $this->conf_tab_arr[$row[2]][$row[4]][$tab_name] = array();
   223                     $tabs[$row[2]][$row[4]][$tab_id] = $tab_name;
   224                 }
   225                 continue;
   226             }
   227             
   228             // group the tab type
   229             if ($row[3] == 'tab') {
   230                 $this->conf_type['tab'][$row[2]][$row[0]] = "config.{$row[2]}.{$row[0]}";
   231                 $this->conf_type['tree'][$row[2]][$row[4]][$row[0]] = "config.{$row[2]}.{$row[0]}";
   232                 
   233                 if (!isset($this->conf_tab_arr[$row[0]])) {
   234                     $this->conf_tab_arr[$row[2]][$row[4]][$row[0]] = array();
   235                     $tabs[$row[2]][$row[4]][$row[5]] = $row[0];
   236                 }
   237                 continue;
   238             }
   239           
   240         }
   241 
   242         // Now figure out other info since tabs are now specified
   243         $sql = "SELECT name, value, group_name, type, subgroup, tab FROM {$_TABLES['conf_values']} WHERE type <> 'tab'";
   244         $result = DB_query($sql);
   245         $false_str = serialize(false);
   246         while ($row = DB_fetchArray($result)) {
   247             // Set any null tab to 0 since they now have been defaulted above
   248             if ($row[5] == '') {
   249                 $row[5] = 0;
   250             }
   251             
   252             // group the subgroup type
   253             if ($row[3] == 'subgroup') {
   254                 $this->conf_type['subgroup'][$row[2]][$row[0]] = $row[0];
   255                 continue;
   256             }
   257 
   258             // group the fieldset type
   259             if ($row[3] == 'fieldset') {
   260                 $this->conf_type['fieldset'][$row[2]][$row[0]] = $row[0];
   261             //    continue;
   262             }               
   263             
   264             if ($row[1] !== 'unset') {
   265                 if (!array_key_exists($row[2], $this->config_array) ||
   266                     !array_key_exists($row[0], $this->config_array[$row[2]])) {
   267                     $value = @unserialize($row[1]);
   268                     if (($value === false) && ($row[1] != $false_str)) {
   269                         if (function_exists('COM_errorLog')) {
   270                             COM_errorLog("Unable to unserialize {$row[1]} for {$row[2]}:{$row[0]}");
   271                         }
   272                     } else {
   273                         $this->config_array[$row[2]][$row[0]] = $value;
   274                         
   275                         if ( strpos($row[3], '@') === 0 ) { // if @
   276                             if ( is_array($value) && !empty($value) ) {
   277                                 $this->conf_tab_arr[$row[2]][$row[4]]
   278                                 [$tabs[$row[2]][$row[4]][$row[5]]][$row[5]][$row[0]] = array_keys($value);
   279                             }
   280                         } else {
   281                             $this->conf_tab_arr[$row[2]][$row[4]]
   282                             [$tabs[$row[2]][$row[4]][$row[5]]][$row[5]][$row[0]] = $row[0];
   283                         }
   284                     }
   285                 }
   286             } else {
   287                 // set to autocomplete only
   288                 $this->conf_tab_arr[$row[2]][$row[4]]
   289                 [$tabs[$row[2]][$row[4]][$row[5]]][$row[5]][$row[0]] = $row[0];
   290             }
   291         }
   292         $this->_post_configuration();
   293 
   294         return $this->config_array;
   295     }
   296 
   297     /**
   298      * Get configurations for particular group.
   299      * 
   300      * @param string        $group  Group name
   301      * @return bool|array           Array of configurations for specified group
   302      *                              or returns false if group doesn't exist
   303      */
   304     function &get_config($group)
   305     {
   306         $retval = false;
   307 
   308         if (array_key_exists($group, $this->config_array)) {
   309 
   310             // an ugly little hack to ensure backward compatibility ...
   311             if ($group == 'Core') {
   312                 global $_DB_mysqldump_path;
   313 
   314                 $_DB_mysqldump_path = $this->config_array[$group]['mysqldump_path'];
   315             }
   316 
   317             return $this->config_array[$group];
   318         }
   319 
   320         return $retval;
   321     }
   322 
   323     /**
   324      * Check if group exists or not
   325      * 
   326      * @param   string $group Group name
   327      * @return  bool          True if group exists
   328      */
   329     function group_exists($group)
   330     {
   331         return array_key_exists($group, $this->config_array);
   332     }
   333 
   334     /**
   335      * This method sets a configuration variable to a value in the database
   336      * and in the current array. If the variable does not already exist,
   337      * nothing will happen.
   338      *
   339      * @param   string  $name        Name of the config parameter to set
   340      * @param   mixed   $value       The value to set the config parameter to
   341      * @return  void
   342      */
   343     function set($name, $value, $group='Core')
   344     {
   345         global $_TABLES;
   346 
   347         $escaped_val = addslashes(serialize($value));
   348         $escaped_name = addslashes($name);
   349         $escaped_grp = addslashes($group);
   350         $sql = "UPDATE {$_TABLES['conf_values']} " .
   351                "SET value = '{$escaped_val}' WHERE " .
   352                "name = '{$escaped_name}' AND group_name = '{$escaped_grp}'";
   353         $this->_DB_escapedQuery($sql);
   354         $this->config_array[$group][$name] = $value;
   355         $this->_post_configuration();
   356     }
   357 
   358     /**
   359      * This method sets the default of a configuration variable to a value in
   360      * the database but not in the current array.
   361      * If the variable does not already exist, nothing will happen.
   362      *
   363      * @param   string $name        Name of the config parameter to set
   364      * @param   mixed  $value       The value to set the config parameter to
   365      * @param   string $group       Config group name ('Core' or plugin name)
   366      * @return  void
   367      */
   368     function set_default($name, $value, $group = 'Core')
   369     {
   370         global $_TABLES;
   371 
   372         $escaped_val = addslashes(serialize($value));
   373         $escaped_name = addslashes($name);
   374         $escaped_grp = addslashes($group);
   375         $sql = "UPDATE {$_TABLES['conf_values']} " .
   376                "SET default_value = '{$escaped_val}' WHERE " .
   377                "name = '{$escaped_name}' AND group_name = '{$escaped_grp}'";
   378         $this->_DB_escapedQuery($sql);
   379     }
   380 
   381     /**
   382      * This method restores the default value (specified in the default_value field)
   383      * of a configuration variable.
   384      * 
   385      * @param   string $name   Configuration variable's name
   386      * @param   string $group  Group name of configuration variable
   387      * @param   int    $sg     Subgroup of configuration variable
   388      * @param   string $tab_id Tab id
   389      * @return  bool           True on succeed
   390      */
   391     function restore_param($name, $group, $sg = null, $tab_id = null)
   392     {
   393         global $_TABLES;
   394         
   395         // check if current user other than Root has access to
   396         $tab_name = $this->_get_tab_name($group, $tab_id);
   397         $ft = $this->conf_type['tab'][$group][$tab_name];
   398         if ( !SEC_inGroup('Root') && !SEC_hasRights($ft) ) {
   399             return false;
   400         }
   401 
   402         $escaped_name = addslashes($name);
   403         $escaped_grp = addslashes($group);
   404 
   405         $result = DB_query("SELECT value, default_value FROM {$_TABLES['conf_values']} WHERE name = '{$escaped_name}' AND group_name = '{$escaped_grp}'");
   406         list($value, $default_value) = DB_fetchArray($result);
   407 
   408         $sql = "UPDATE {$_TABLES['conf_values']} ";
   409         if ($value == 'unset') {
   410             $default_value = addslashes($default_value);
   411             $sql .= "SET value = '{$default_value}', default_value = 'unset:{$default_value}'";
   412         } else {
   413             $sql .= "SET value = default_value";
   414         }
   415         $sql .= " WHERE name = '{$escaped_name}' AND group_name = '{$escaped_grp}'";
   416         $this->_DB_escapedQuery($sql);
   417         
   418         return true;
   419     }
   420 
   421     /**
   422      * This method sets a configuration variable's value to 'unset'.
   423      * 
   424      * @param   string $name   Configuration variable's name
   425      * @param   string $group  Group name of configuration variable
   426      * @param   int    $sg     Subgroup of configuration variable
   427      * @param   string $tab_id Tab id
   428      * @return  bool           True on succeed
   429      */
   430     function unset_param($name, $group, $sg = null, $tab_id = '')
   431     {
   432         global $_TABLES;
   433         
   434         // check if current user other than Root has access to
   435         $tab_name = $this->_get_tab_name($group, $tab_id);
   436         $ft = $this->conf_type['tab'][$group][$tab_name];
   437         if ( !SEC_inGroup('Root') && !SEC_hasRights($ft) ) {
   438             return false;
   439         }
   440 
   441         $escaped_name = addslashes($name);
   442         $escaped_grp = addslashes($group);
   443         $default_value = DB_getItem($_TABLES['conf_values'], 'default_value',
   444                 "name = '{$escaped_name}' AND group_name = '{$escaped_grp}'");
   445         $sql = "UPDATE {$_TABLES['conf_values']} SET value = 'unset'";
   446         if (substr($default_value, 0, 6) == 'unset:') {
   447             $default_value = addslashes(substr($default_value, 6));
   448             $sql .= ", default_value = '{$default_value}'";
   449         }
   450         $sql .= " WHERE name = '{$escaped_name}' AND group_name = '{$escaped_grp}'";
   451         $this->_DB_escapedQuery($sql);
   452         
   453         return true;
   454     }
   455 
   456     /**
   457      * Adds a configuration variable to the config object
   458      *
   459      * @param string  $param_name        name of the parameter to add
   460      * @param mixed   $default_value     the default value of the parameter
   461      *                                   (also will be the initial value)
   462      * @param string  $type              the type of the configuration variable
   463      *
   464      *    If the configuration variable is an array, prefix this string with
   465      *    '@' if the administrator should NOT be able to add or remove keys
   466      *    '*' if the administrator should be able to add named keys
   467      *    '%' if the administrator should be able to add numbered keys
   468      *    These symbols can be repeated like such: @@text if the configuration
   469      *    variable is an array of arrays of text.
   470      *    The base variable types are:
   471      *    'text'    textbox displayed     string  value stored
   472      *    'select'  selectbox displayed   string  value stored
   473      *    'hidden'  no display            string  value stored
   474      *
   475      * @param string  $subgroup          subgroup of the variable
   476      *                                   (the second row of tabs on the user interface)
   477      * @param string  $fieldset          the fieldset to display the variable under
   478      * @param array   $selection_array   possible selections for the 'select' type
   479      *                                   this MUST be passed if you use the 'select'
   480      *                                   type
   481      * @param int     $sort              sort rank on the user interface (ascending)
   482      *
   483      * @param boolean $set               whether or not this parameter is set to config_array property
   484      * @param string  $group             group of the variable
   485      * @param string  $tab               the tab to display the variable under
   486      */
   487     function add($param_name, $default_value, $type, $subgroup, $fieldset=null,
   488          $selection_array=null, $sort=0, $set=true, $group='Core', $tab=null)
   489     {
   490         global $_TABLES;
   491 
   492         $Qargs = array($param_name,
   493                        $set ? serialize($default_value) : 'unset',
   494                        $type,
   495                        $subgroup,
   496                        $group,
   497                        ($selection_array === null ?
   498                             -1 : $selection_array),
   499                        $sort,
   500                        ($fieldset === null ?
   501                              0 : $fieldset),
   502                        serialize($default_value)
   503                       );
   504 
   505         $columns = 'name, value, type, subgroup, group_name, selectionArray, sort_order, fieldset, default_value';
   506 
   507         // special handling of $tab for backward compatibility
   508         if ($tab !== null) {
   509             $columns .= ', tab';
   510             $Qargs[9] = $tab;
   511         }
   512         $Qargs = array_map('addslashes', $Qargs);
   513 
   514         // Now add in config item
   515         $sql = "INSERT INTO {$_TABLES['conf_values']} ($columns) VALUES ("
   516              . "'{$Qargs[0]}',"
   517              . "'{$Qargs[1]}',"
   518              . "'{$Qargs[2]}',"
   519              . "{$Qargs[3]},"
   520              . "'{$Qargs[4]}',"
   521              . "{$Qargs[5]},"
   522              . "{$Qargs[6]},"
   523              . "'{$Qargs[7]}',"
   524              . "'{$Qargs[8]}'";
   525         if ($tab !== null) {
   526             $sql .= ",{$Qargs[9]}";
   527         }
   528         $sql .= ')';
   529 
   530         $this->_DB_escapedQuery($sql);
   531 
   532         if ($set) {
   533             $this->config_array[$group][$param_name] = $default_value;
   534         }
   535     }
   536 
   537     /**
   538      * Permanently deletes a parameter
   539      * @param string $param_name This is the name of the parameter to delete
   540      * @param string $group      Configuraton group name      
   541      */
   542     function del($param_name, $group)
   543     {
   544         DB_delete($GLOBALS['_TABLES']['conf_values'],
   545                   array('name', 'group_name'),
   546                   array(addslashes($param_name), addslashes($group)));
   547         unset($this->config_array[$group][$param_name]);
   548     }
   549 
   550     /**
   551      * Gets extended (GUI related) information from the database
   552      * @param string subgroup            filters by subgroup
   553      * @return array(string => string => array(string => mixed))
   554      *    Array keys are fieldset => parameter named => information array
   555      */
   556     function _get_extended($subgroup, $group)
   557     {
   558         global $_TABLES, $LANG_confignames, $LANG_configselects;
   559 
   560         $q_string = "SELECT name, type, selectionArray, "
   561             . "tab, value, default_value, fieldset FROM {$_TABLES['conf_values']}" .
   562             " WHERE group_name='{$group}' AND subgroup='{$subgroup}' " .
   563             " AND (type <> 'tab' AND type <> 'subgroup') " .
   564             " ORDER BY tab,fieldset,sort_order ASC";
   565 
   566         $Qresult = DB_query($q_string);
   567         $res = array();
   568         if (!array_key_exists($group, $LANG_configselects)) {
   569             $LANG_configselects[$group] = array();
   570         }
   571         if (!array_key_exists($group, $LANG_confignames)) {
   572             $LANG_confignames[$group] = array();
   573         }
   574         while ($row = DB_fetchArray($Qresult)) {
   575             $cur = $row;
   576 
   577             if ($cur[3] == '') {$cur[3] = 0;}  // If tab is null then old plugin so set default tab
   578 
   579             if (substr($cur[5], 0, 6) == 'unset:') {
   580                 $cur[5] = true;
   581             } else {
   582                 $cur[5] = false;
   583             }
   584             $res[$cur[3]][$cur[0]] =
   585                 array('display_name' =>
   586                       (array_key_exists($cur[0], $LANG_confignames[$group]) ?
   587                        $LANG_confignames[$group][$cur[0]]
   588                        : $cur[0]),
   589                       'type' =>
   590                       (($cur[4] == 'unset') ?
   591                        'unset' : $cur[1]),
   592                       'selectionArray' =>
   593                       (($cur[2] != -1) ?
   594                        //isset($LANG_configselects[$group][$cur[2]]) : null),
   595                        $LANG_configselects[$group][$cur[2]] : null),
   596                       'value' =>
   597                       (($cur[4] == 'unset') ?
   598                        'unset' : unserialize($cur[4])),
   599                       'fieldset' => $cur[6], 
   600                       'reset' => $cur[5]);
   601         }
   602 
   603         return $res;
   604     }
   605 
   606     /**
   607      * Changes any config settings that depend on other configuration settings.
   608      * Called by config::initConfig and config::set
   609      * 
   610      * @return voif
   611      */
   612     function _post_configuration()
   613     {
   614         global $_USER;
   615 
   616         if (empty($_USER['theme'])) {
   617             if (! empty($this->config_array['Core']['theme'])) {
   618                 $theme = $this->config_array['Core']['theme'];
   619             }
   620         } else {
   621             $theme = $_USER['theme'];
   622         }
   623 
   624         if (! empty($theme)) {
   625             if (! empty($this->config_array['Core']['path_themes'])) {
   626                 $this->config_array['Core']['path_layout'] = $this->config_array['Core']['path_themes'] . $theme . '/';
   627             }
   628             if (! empty($this->config_array['Core']['site_url'])) {
   629                 $this->config_array['Core']['layout_url'] = $this->config_array['Core']['site_url'] . '/layout/' . $theme;
   630             }
   631         }
   632 
   633         $methods = array('standard', 'openid', '3rdparty', 'oauth');
   634         $methods_disabled = 0;
   635         foreach ($methods as $m) {
   636             if (isset($this->config_array['Core']['user_login_method'][$m]) &&
   637                     !$this->config_array['Core']['user_login_method'][$m]) {
   638                 $methods_disabled++;    
   639             }
   640         }
   641         if ($methods_disabled == count($methods)) {
   642             // just to make sure people don't lock themselves out of their site
   643             $this->config_array['Core']['user_login_method']['standard'] = true;
   644 
   645             // TBD: ensure that we have a Root user able to log in with the
   646             //      enabled login method(s)
   647         }
   648     }
   649 
   650     /**
   651      * Get configuration groups for current logged user.
   652      * Plugins being disabled are ignored. Configurations
   653      * that user doesn't access to are ignored.
   654      * 
   655      * @return array Array of configuraton groups.
   656      */
   657     function _get_groups()
   658     {
   659         global $_TABLES, $_RIGHTS;
   660         
   661         $groups = array_keys($this->config_array);
   662         $num_groups = count($groups);
   663         for ($i = 0; $i < $num_groups; $i++) {
   664             $g = $groups[$i];
   665             // Only collect plugins that are enabled
   666             if ($g != 'Core') {
   667                 $enabled = DB_getItem($_TABLES['plugins'], 'pi_enabled',
   668                                       "pi_name = '$g'");
   669                 if (isset($enabled) && ($enabled == 0)) {
   670                     unset($groups[$i]);
   671                     continue;
   672                 }
   673             }
   674             
   675             // check if current user other than Root has access to
   676             $tabs = array_values($this->conf_type['tab'][$g]);
   677             if ( !SEC_inGroup('Root') && !SEC_hasRights($tabs, 'OR') ) {
   678                 unset($groups[$i]);
   679             }
   680         }
   681         
   682         return $groups;
   683     }
   684 
   685     /**
   686      * Get configuration subgroups for particular configuration group.
   687      * 
   688      * @param   string $group Configuration group name
   689      * @return  array         Array of subgroups that belong to configuration $group
   690      */
   691     function _get_sgroups($group)
   692     {
   693         global $_TABLES;
   694 
   695         $q_string = "SELECT name,subgroup FROM {$_TABLES['conf_values']} WHERE "
   696                   . "type = 'subgroup' AND group_name = '$group' "
   697                   . "ORDER BY subgroup";
   698         $retval = array();
   699         
   700         $res = DB_query($q_string);
   701         while ($row = DB_fetchArray($res)) {
   702             // check if current user has access to current subgroup
   703             $tabs = array_values($this->conf_type['tree'][$group][$row['subgroup']]);
   704             if ( !SEC_inGroup('Root') && !SEC_hasRights($tabs, 'OR') ) {
   705                 continue;
   706             }
   707             $retval[$row['name']] = $row['subgroup'];
   708         }
   709 
   710         return $retval;
   711     }
   712     
   713     
   714     /**
   715      * Get tab name based on sepecified group name and tab id.
   716      * 
   717      * @param string $group Group name
   718      * @param int $tab_id tab id
   719      */
   720     function _get_tab_name($group, $tab_id) {
   721         global $_TABLES;
   722         
   723         return DB_getItem($_TABLES['conf_values'], 'name',
   724                     "type = 'tab' AND tab = $tab_id AND group_name = '$group'");
   725         
   726     }
   727     
   728     /**
   729      * Get fieldset name based on sepecified tab id.
   730      * 
   731      * @param string $tab_id tab id
   732      * @param int $fs_id fieldset id
   733      */
   734     function _get_fs_name($tab_id, $fs_id) {
   735         global $_TABLES;
   736         
   737         return DB_getItem($_TABLES['conf_values'], 'name',
   738                     "type = 'fieldset' AND fieldset = $fs_id AND tab = '$tab_id'");
   739         
   740     }
   741 
   742     /**
   743      * This function is responsible for creating the configuration GUI
   744      * 
   745      * @oaram string $grp     This is the group name to load the gui for.
   746      * @param string sg       This is the subgroup name to load the gui for.
   747      *                        If nothing is passed, it will display the first
   748      *                        (alpha) subgroup.
   749      * @param mixed  $change_result
   750      *                        This is an array of what changes were made to the
   751      *                        configuration - if it is passed, it will display
   752      *                        the "Changes" message box.
   753      */
   754     function get_ui($grp, $sg='0', $change_result=null)
   755     {
   756         global $_CONF, $LANG_CONFIG, $LANG_configsubgroups, $LANG_tab, $LANG_fs,
   757             $_SCRIPTS, $LANG01;
   758 
   759         if(!array_key_exists($grp, $LANG_configsubgroups)) {
   760             $LANG_configsubgroups[$grp] = array();
   761         }
   762         
   763         // denied users that don't have access to configuration
   764         $groups = $this->_get_groups();
   765         if (empty($groups)) {
   766             return config::_UI_perm_denied();
   767         }
   768         
   769         if (!isset($sg) OR empty($sg)) {
   770             $sg = '0';
   771             
   772             // get default subgroup for non Root user
   773             if ( !SEC_inGroup('Root') ) {
   774                 $default_sg = $this->_get_sgroups($grp);
   775                 if ( !empty($default_sg) ) {
   776                     $default_sg = array_values($default_sg);
   777                     $sg = $default_sg[0];
   778                 } else {
   779                     return config::_UI_perm_denied();
   780                 }
   781             }
   782         }
   783         
   784         $t = COM_newTemplate($_CONF['path_layout'] . 'admin/config');
   785         $t->set_file(array('main' => 'configuration.thtml',
   786                            'menugroup' => 'menu_element.thtml'));
   787 
   788         $link_message = $LANG01[139];   
   789         $t->set_var('noscript', COM_getNoScript(false, '', $link_message));
   790         // Hide the Configuration as Javascript is currently required. If JS is enabled then the JS below will un-hide it
   791         $js = 'document.getElementById("geeklog_config_editor").style.display="";';                 
   792         $_SCRIPTS->setJavaScript($js, true);        
   793         
   794         $t->set_var('gltoken_name', CSRF_TOKEN);
   795         $t->set_var('gltoken', SEC_createToken());
   796         
   797         // set javascript variable for autocomplete
   798         $js = $this->_UI_autocomplete_data();
   799         // set javascript variable for image spinner
   800         $js .= $this->_UI_js_image_spinner();        
   801         $js .= "var frmGroupAction = '" . $_CONF['site_admin_url'] . "/configuration.php';";
   802         $_SCRIPTS->setJavaScript($js, true);
   803 
   804         $this->flag_version_2 = version_compare($_CONF['supported_version_theme'], '2.0.0', '>=');
   805 
   806         if ($this->flag_version_2 == true) {
   807             $_SCRIPTS->setJavaScriptFile('admin.configuration', '/javascript/admin.configuration.js');
   808         } else {
   809             $_SCRIPTS->setJavaScriptFile('admin.configuration', '/javascript/ver.1.8/admin.configuration.js');
   810         }
   811 
   812         
   813         $t->set_var('search_configuration_label', $LANG_CONFIG['search_configuration_label']);
   814         if (isset($_POST['search-configuration-cached'])) {
   815             $t->set_var('search_configuration_value', $_POST['search-configuration-cached']);
   816         } else {
   817             $t->set_var('search_configuration_value', '');
   818         }
   819         if (isset($_POST['tab-id-cached'])) {
   820             $t->set_var('tab_id_value', $_POST['tab-id-cached']);
   821         } else {
   822             $t->set_var('tab_id_value', '');
   823         }
   824 
   825         $t->set_var('lang_save_changes', $LANG_CONFIG['save_changes']);
   826         $t->set_var('lang_reset_form', $LANG_CONFIG['reset_form']);
   827         
   828         $t->set_var('open_group', $grp);
   829 
   830         $outerloopcntr = 1;
   831         if (count($groups) > 0) {
   832             $t->set_block('menugroup', 'subgroup-selector', 'subgroups');
   833             foreach ($groups as $group) {
   834                 $t->set_var("select_id", ($group === $grp ? 'id="current"' : ''));
   835                 $t->set_var("group_select_value", $group);
   836                 $t->set_var("group_display", ucwords($group));
   837                 $subgroups = $this->_get_sgroups($group);
   838                 $innerloopcntr = 1;
   839                 foreach ($subgroups as $sgname => $sgroup) {
   840                     if ($grp == $group AND $sg == $sgroup) {
   841                         $t->set_var('group_active_name', ucwords($group));
   842                         if (isset($LANG_configsubgroups[$group][$sgname])) {
   843                             $t->set_var('subgroup_active_name',
   844                                     $LANG_configsubgroups[$group][$sgname]);
   845                         } else if (isset($LANG_configsubgroups[$group][$sgroup])) {
   846                             $t->set_var('subgroup_active_name',
   847                                     $LANG_configsubgroups[$group][$sgroup]);
   848                         } else {
   849                             $t->set_var('subgroup_active_name', $sgname);
   850                         }
   851                         $t->set_var('select_id', 'id="current"');
   852                     } else {
   853                         $t->set_var('select_id', '');
   854                     }
   855                     $t->set_var('subgroup_name', $sgroup);
   856                     if (isset($LANG_configsubgroups[$group][$sgname])) {
   857                         $t->set_var('subgroup_display_name',
   858                                     $LANG_configsubgroups[$group][$sgname]);
   859                     } else {
   860                         $t->set_var('subgroup_display_name', $sgname);
   861                     }
   862                     if ($innerloopcntr == 1) {
   863                         $t->parse('subgroups', "subgroup-selector");
   864                     } else {
   865                         $t->parse('subgroups', "subgroup-selector", true);
   866                     }
   867                     $innerloopcntr++;
   868                 }
   869                 $t->set_var('cntr',$outerloopcntr);
   870                 $t->parse("menu_elements", "menugroup", true);
   871                 $outerloopcntr++;
   872             }
   873         } else {
   874             $t->set_var('hide_groupselection','none');
   875         }
   876 
   877         $t->set_var('open_sg', $sg);
   878         $t->set_block('main','tab','sg_contents');
   879         $t->set_block('tab', 'notes', 'tab_notes');
   880 
   881         $ext_info = $this->_get_extended($sg, $grp);
   882         $tab_li = '<ul>';
   883         foreach ($ext_info as $tab => $params) {
   884             $tab_contents = '';
   885             $current_fs = '';
   886             $fs_flag = false;
   887             $table_flag = false;
   888             foreach ($params as $name => $e) {
   889                 if ($e['type'] == 'fieldset' AND $e['fieldset'] != $current_fs) {
   890                     $fs_flag = true;
   891                     if ($current_fs != '') {
   892 
   893                         if ($this->flag_version_2 == true) {
   894                             $tab_contents .= '</div></fieldset><!-- END fieldset -->';
   895                         } else {
   896                             $tab_contents .= '</table></fieldset><!-- END fieldset -->';
   897                         }
   898 
   899                         $table_flag = false;
   900                     }
   901                     $tab_contents .= '<!-- BEGIN fieldset --><fieldset><legend>' . $LANG_fs[$grp][$e['display_name']] . '</legend>';
   902                     $current_fs = $e['fieldset'];
   903                 }
   904                 if (!$table_flag) {
   905 
   906                     if ($this->flag_version_2 == true) {
   907                         $tab_contents .= '<div class="inputTable">';
   908                     } else {
   909                         $tab_contents .= '<table class="inputTable">';
   910                     }
   911 
   912                     $table_flag = true;
   913                 }
   914 
   915                 if ($this->flag_version_2 == true) {
   916                     $tab_contents .=
   917                         $this->_UI_get_conf_element_2($grp, $name,
   918                                                    $e['display_name'],
   919                                                    $e['type'],
   920                                                    $e['value'],
   921                                                    $e['selectionArray'], false,
   922                                                    $e['reset']);
   923                 } else {
   924                     $tab_contents .=
   925                         $this->_UI_get_conf_element($grp, $name,
   926                                                    $e['display_name'],
   927                                                    $e['type'],
   928                                                    $e['value'],
   929                                                    $e['selectionArray'], false,
   930                                                    $e['reset']);
   931                 }
   932             }
   933 
   934             if ($table_flag) {
   935                 if ($this->flag_version_2 == true) {
   936                     $tab_contents .= '</div>';
   937                 } else {
   938                     $tab_contents .= '</table>';
   939                 }
   940             }
   941 
   942             if ($fs_flag) {
   943                 $tab_contents .= '</fieldset><!-- END fieldset -->';
   944             }
   945             
   946             // check if current user has access to current tab
   947             $tab_name = "config.{$grp}." . $this->_get_tab_name($grp, $tab);
   948             if ( !SEC_inGroup('Root') && !SEC_hasRights($tab_name) ) {
   949                 continue;
   950             }
   951             // tab content
   952             $tab_display = $this->_UI_get_tab($grp, $tab_contents, $tab, $t);
   953             
   954             // tab list
   955             $tab_li .= '<li><a href="#tab-' . $tab . '">' . $tab_display . '</a></li>';
   956         }
   957         $tab_li .= '</ul>';
   958         $t->set_var('tab_li', $tab_li);
   959         
   960         $_SCRIPTS->setJavaScriptLibrary('jquery.ui.autocomplete');
   961         $_SCRIPTS->setJavaScriptLibrary('jquery.ui.tabs');
   962         
   963         $t->set_var('config_menu',$this->_UI_configmanager_menu($grp,$sg));
   964         
   965         // message box
   966         if ($change_result != null AND $change_result !== array()) {
   967             $t->set_var('lang_changes_made', $LANG_CONFIG['changes_made'] . ':');
   968             $t->set_var('change_block',$this->_UI_get_change_block($change_result, $grp, $sg));
   969         } else {
   970             $t->set_var('show_changeblock','none');
   971         }
   972         if ( !empty($this->validationErrors) ) {
   973             $t->set_var('lang_changes_made', '');
   974             $t->set_var('show_changeblock', '');
   975             $t->set_var('change_block',$this->_UI_get_change_block(NULL, $grp, $sg));
   976             $t->set_var('lang_error_validation_occurs', $LANG_CONFIG['error_validation_occurs'] . ' :');
   977             $t->set_var('error_validation_class', ' error_validation');
   978         }
   979         
   980         $display = $t->finish($t->parse("OUTPUT", "main"));
   981         $display = COM_createHTMLDocument($display, array('what' => 'none', 'pagetitle' => $LANG_CONFIG['title'], 'rightblock' => false));
   982 
   983         return $display;
   984     }
   985 
   986     /**
   987      * Get messages to display when changes were made to the configuration.
   988      * 
   989      * @param  array  $changes Array of changes. Keys are configuration
   990      *                         paramater name.
   991      * @param  string $group   Configuration group
   992      * @param  int    $sg      Configuration subgroup
   993      * @return string          string of HTML to be displayed on message box 
   994      */
   995     function _UI_get_change_block($changes, $group = null, $sg = null)
   996     {
   997         $display = '';
   998         $anchors = array();
   999         
  1000         if ( empty($this->validationErrors) ) {
  1001             if ($changes != null AND $changes !== array()) {
  1002                 foreach ($changes as $param_name => $success) {
  1003                     if ( isset($this->changedArray[$group][$param_name]) ) {
  1004                         foreach ($this->changedArray[$group][$param_name] as $_param_name => $_success) {
  1005                             $anchors[] = ' <a href="#' . $param_name . '[' . $_param_name . ']' .
  1006                                          '" class="select_config"' .
  1007                                          (($group !== null) ? ' group="' . $group . '"' : '') .
  1008                                          (($sg !== null) ? ' subgroup="' . $sg . '"' : '') .
  1009                                          '>' . $param_name . '[' . $_param_name . ']' . '</a>';
  1010                         }
  1011                     } else {
  1012                         $anchors[] = ' <a href="#' . $param_name . '" class="select_config"' .
  1013                                      (($group !== null) ? ' group="' . $group . '"' : '') .
  1014                                      (($sg !== null) ? ' subgroup="' . $sg . '"' : '') .
  1015                                      '>' . $param_name . '</a>';
  1016                     }
  1017                 }
  1018             }
  1019         } else {
  1020             foreach ( $this->validationErrors as $grp => $errors ) {
  1021                 foreach ( $errors as $param_name => $error ) {
  1022                     $anchors[] = ' <a href="#' . $param_name . '" class="select_config"' .
  1023                                  (($group !== null) ? ' group="' . $group . '"' : '') .
  1024                                  (($sg !== null) ? ' subgroup="' . $sg . '"' : '') .
  1025                                  '>' . $param_name . '</a>';
  1026                 }
  1027             }
  1028         }
  1029         
  1030         if ( !empty($anchors) ) {
  1031             $display = implode(',', $anchors);
  1032         }
  1033         
  1034         return $display;
  1035     }
  1036     
  1037     /**
  1038      * Set tab from configuration where tab = $tab_id under the group $group
  1039      * with content $contents to template $t
  1040      * 
  1041      * @param  string $group Configuration group
  1042      * @param  string $contents Contents
  1043      * @param  int    $tab_id tab id
  1044      * @param  object $t        Template object
  1045      * @return string tab name to display based on current language
  1046      */
  1047     function _UI_get_tab($group, $contents, $tab_id, &$t)
  1048     {
  1049         global $_TABLES, $LANG_tab, $LANG_CONFIG;
  1050         
  1051         if (!array_key_exists($group, $LANG_tab)) {
  1052             $LANG_tab[$group] = array();
  1053         }
  1054         $t->set_var('tab_contents', $contents);
  1055         $tab_index = DB_getItem($_TABLES['conf_values'], 'name',
  1056                         "type = 'tab' AND tab = $tab_id AND group_name = '$group'");
  1057         $tab_display = '';
  1058         if (empty($tab_index)) {
  1059             if (empty($LANG_tab[$group][$tab_id])) {
  1060                $tab_display = $LANG_CONFIG['default_tab_name'];
  1061             } else {
  1062                 $tab_display = $LANG_tab[$group][$tab_id];
  1063             }
  1064         } else if (isset($LANG_tab[$group][$tab_index])) {
  1065             $tab_display = $LANG_tab[$group][$tab_index];
  1066         } else {
  1067             $tab_display = $tab_index;
  1068         }
  1069         $t->set_var('tab_id', "tab-{$tab_id}");
  1070         $t->set_var('tab_display', $tab_display);
  1071         $t->set_var('tab_notes', '');
  1072         $t->parse('sg_contents', 'tab', true);
  1073         
  1074         // used by tab_li
  1075         return $tab_display;
  1076     }
  1077 
  1078     /**
  1079      * Set fieldset from configuration where fieldset = $fs_id under the group $group
  1080      * with content $contents to template $t
  1081      * 
  1082      * @param  string $group
  1083      * @param  string $contents Contents
  1084      * @param  int    $fs_id
  1085      * @param  object $t        Template object
  1086      * @return void
  1087      */
  1088     function _UI_get_fs($group, $contents, $fs_id, &$t)
  1089     {
  1090         global $_TABLES, $LANG_fs;
  1091         
  1092         if (!array_key_exists($group, $LANG_fs)) {
  1093             $LANG_fs[$group] = array();
  1094         }
  1095         $t->set_var('fs_contents', $contents);
  1096         $fs_index = DB_getItem($_TABLES['conf_values'], 'name',
  1097                         "type = 'fieldset' AND fieldset = $fs_id AND group_name = '$group'");
  1098         if (empty($fs_index)) {
  1099             $t->set_var('fs_display', $LANG_fs[$group][$fs_id]);
  1100         } else if (isset($LANG_fs[$group][$fs_index])) {
  1101             $t->set_var('fs_display', $LANG_fs[$group][$fs_index]);
  1102         } else {
  1103             $t->set_var('fs_display', $fs_index);
  1104         }
  1105         $t->set_var('fs_notes', '');
  1106         $t->parse('sg_contents', 'fieldset', true);
  1107     }
  1108 
  1109     /**
  1110      * Returns a page for permission denied
  1111      * 
  1112      * @return  string HTML for permission denied page
  1113      */
  1114     function _UI_perm_denied()
  1115     {
  1116         global $_USER, $MESSAGE;
  1117 
  1118         $display = COM_showMessageText($MESSAGE[29], $MESSAGE[30]);
  1119         $display = COM_createHTMLDocument($display, array('pagetitle' => $MESSAGE[30]));
  1120         COM_accessLog("User {$_USER['username']} tried to illegally access the config administration screen.");
  1121 
  1122         return $display;
  1123     }
  1124 
  1125     /**
  1126      * Get a parsed config element based on group $group, name $name,
  1127      * type $type, value to be shown $val and label $display_name to be shown  
  1128      * on the left based on language.
  1129      * 
  1130      * @param  string $group Configuration group.
  1131      * @param  string $name Configuration name on table.
  1132      * @param  string $display_name Configuration display name based on language.
  1133      * @param  string $type Configuration type such as select, text, textarea, @select, etc.
  1134      * @param  string $val Value of configuration
  1135      * @param  mixed  $selectionArray Array of option of select element
  1136      * @param  bool   $deleteable If configuration is deleteable
  1137      * @param  bool   $allow_reset Allow set and unset of configuration
  1138      * @return
  1139      */
  1140     function _UI_get_conf_element($group, $name, $display_name, $type, $val,
  1141                                   $selectionArray = null , $deletable = false,
  1142                                   $allow_reset = false)
  1143     {
  1144         global $_CONF, $LANG_CONFIG;
  1145 
  1146         $t = COM_newTemplate($GLOBALS['_CONF']['path_layout'] . 'admin/config');
  1147         $t -> set_file('element', 'config_element.thtml');
  1148 
  1149         $blocks = array('delete-button', 'text-element', 'placeholder-element',
  1150                         'select-element', 'list-element', 'unset-param',
  1151                         'keyed-add-button', 'unkeyed-add-button', 'text-area',
  1152                         'validation_error_block');
  1153         foreach ($blocks as $block) {
  1154             $t->set_block('element', $block);
  1155         }
  1156 
  1157         $t->set_var('lang_restore', $LANG_CONFIG['restore']);
  1158         $t->set_var('lang_enable', $LANG_CONFIG['enable']);
  1159         $t->set_var('lang_add_element', $LANG_CONFIG['add_element']);
  1160 
  1161         $t->set_var('name', $name);
  1162         $t->set_var('id_name', str_replace(array('[', ']'), array('_', ''), $name));
  1163         $t->set_var('display_name', $display_name);
  1164         
  1165         // check tmp values
  1166         if ( isset($this->tmpValues[$group][$name]) ) {
  1167             $val = $this->tmpValues[$group][$name];
  1168         }
  1169         
  1170         if (!is_array($val)) {
  1171             if (is_float($val)) {
  1172                 /**
  1173                 * @todo FIXME: for Locales where the comma is the decimal
  1174                 *              separator, patch output to a decimal point
  1175                 *              to prevent it being cut off by COM_applyFilter
  1176                 */
  1177                 $t->set_var('value', str_replace(',', '.', $val));
  1178             } else {
  1179                 $t->set_var('value', htmlspecialchars($val));
  1180             }
  1181         }
  1182         
  1183         // if there is a error message to shown
  1184         if ( isset($this->validationErrors[$group][$name]) ) {
  1185             $t->set_var('validation_error_message', $this->validationErrors[$group][$name]);
  1186             $t->set_var('error_block', $t->parse('output', 'validation_error_block'));
  1187             $t->set_var('error_class', ' input_error');
  1188             $t->set_var('value', $this->validationErrorValues[$group][$name]);
  1189         } else {
  1190             $t->set_var('error_class', '');
  1191             $t->set_var('error_block', '');
  1192         }
  1193         
  1194         if ($deletable) {
  1195             $t->set_var('delete', $t->parse('output', 'delete-button'));
  1196         } else {
  1197             if ($allow_reset) {
  1198                 $t->set_var('unset_link',
  1199                         "(<a href=\"#{$name}\" class=\"unset_param\" title='"
  1200                         . $LANG_CONFIG['disable'] . "'>X</a>)");
  1201             }
  1202             if (($a = strrchr($name, '[')) !== FALSE) {
  1203                 $on = substr($a, 1, -1);
  1204                 $o = str_replace(array('[', ']'), array('_', ''), $name);
  1205             } else {
  1206                 $o = $name;
  1207                 $on = $name;
  1208             }
  1209             if (! is_numeric($on)) {
  1210                 $this->_set_ConfigHelp($t, $group, $o);
  1211             }
  1212         }
  1213         if ($type == "unset") {
  1214             return $t->finish($t->parse('output', 'unset-param'));
  1215         } elseif ($type == "text") {
  1216             return $t->finish($t->parse('output', 'text-element'));
  1217         } elseif ($type == "textarea") {
  1218             return $t->finish($t->parse('output', 'text-area'));
  1219         } elseif ($type == "placeholder") {
  1220             return $t->finish($t->parse('output', 'placeholder-element'));
  1221         } elseif ($type == 'select') {
  1222             // if $name is like "blah[0]", separate name and index
  1223             $n = explode('[', $name);
  1224             $name = $n[0];
  1225             $index = null;
  1226             if (count($n) == 2) {
  1227                 $i = explode(']', $n[1]);
  1228                 $index = $i[0];
  1229             }
  1230             $type_name = $type . '_' . $name;
  1231             if ($group == 'Core') {
  1232                 $fn = 'configmanager_' . $type_name . '_helper';
  1233             } else {
  1234                 $fn = 'plugin_configmanager_' . $type_name . '_' . $group;
  1235             }
  1236             if (function_exists($fn)) {
  1237                 if ($index === null) {
  1238                     $selectionArray = $fn();
  1239                 } else {
  1240                     $selectionArray = $fn($index);
  1241                 }
  1242             } else if (is_array($selectionArray)) {
  1243                 // leave sorting to the function otherwise
  1244                 uksort($selectionArray, 'strcasecmp');
  1245             }
  1246             if (! is_array($selectionArray)) {
  1247                 return $t->finish($t->parse('output', 'text-element'));
  1248             }
  1249 
  1250             $t->set_block('select-element', 'select-options', 'myoptions');
  1251             foreach ($selectionArray as $sName => $sVal) {
  1252                 if (is_bool($sVal)) {
  1253                     $t->set_var('opt_value', $sVal ? 'b:1' : 'b:0');
  1254                 } else {
  1255                     $t->set_var('opt_value', $sVal);
  1256                 }
  1257                 $t->set_var('opt_name', $sName);
  1258                 $t->set_var('selected', ($val == $sVal ? 'selected="selected"' : ''));
  1259                 $t->parse('myoptions', 'select-options', true);
  1260             }
  1261             if ($index == 'placeholder') {
  1262                 $t->set_var('hide_row', ' style="display:none;"');
  1263             }
  1264             return $t->parse('output', 'select-element');
  1265         } elseif (strpos($type, '@') === 0) {
  1266             $result = '';
  1267             foreach ($val as $valkey => $valval) {
  1268                 $result .= config::_UI_get_conf_element($group,
  1269                                 $name . '[' . $valkey . ']',
  1270                                 $display_name . '[' . $valkey . ']',
  1271                                 substr($type, 1), $valval, $selectionArray,
  1272                                 false);
  1273             }
  1274             return $result;
  1275         } elseif (strpos($type, "*") === 0 || strpos($type, "%") === 0) {
  1276             $t->set_var('arr_name', $name);
  1277             $t->set_var('array_type', $type);
  1278             $button = $t->parse('output', (strpos($type, "*") === 0 ?
  1279                                            'keyed-add-button' :
  1280                                            'unkeyed-add-button'));
  1281             $t->set_var('my_add_element_button', $button);
  1282             $result = "";
  1283             if ($type == '%select') {
  1284                 $result .= config::_UI_get_conf_element($group,
  1285                                 $name . '[placeholder]', 'placeholder',
  1286                                 substr($type, 1), 'placeholder', $selectionArray,
  1287                                 true);
  1288             }
  1289             foreach ($val as $valkey => $valval) {
  1290                 $result .= config::_UI_get_conf_element($group,
  1291                                 $name . '[' . $valkey . ']', $valkey,
  1292                                 substr($type, 1), $valval, $selectionArray,
  1293                                 true);
  1294             }
  1295             $t->set_var('my_elements', $result);
  1296             // if the values are indexed numerically, add a class to the table
  1297             // for identification. The UI code can take advantage of it
  1298             if ($val === array_values($val)) {
  1299                 $t->set_var('arr_table_class_list', 'numerical_config_list');
  1300             }
  1301             return $t->parse('output', 'list-element');
  1302         }
  1303     }
  1304 
  1305     /**
  1306      * Get a parsed config element based on group $group, name $name,
  1307      * type $type, value to be shown $val and label $display_name to be shown  
  1308      * on the left based on language.
  1309      * 
  1310      * @param  string $group Configuration group.
  1311      * @param  string $name Configuration name on table.
  1312      * @param  string $display_name Configuration display name based on language.
  1313      * @param  string $type Configuration type such as select, text, textarea, @select, etc.
  1314      * @param  string $val Value of configuration
  1315      * @param  mixed  $selectionArray Array of option of select element
  1316      * @param  bool   $deleteable If configuration is deleteable
  1317      * @param  bool   $allow_reset Allow set and unset of configuration
  1318      * @return
  1319      */
  1320     function _UI_get_conf_element_2($group, $name, $display_name, $type, $val,
  1321                                   $selectionArray = null , $deletable = false,
  1322                                   $allow_reset = false)
  1323     {
  1324         global $_CONF, $LANG_CONFIG;
  1325 
  1326         $t = COM_newTemplate($GLOBALS['_CONF']['path_layout'] . 'admin/config');
  1327         $t -> set_file('element', 'config_element_2.thtml');
  1328 
  1329         $blocks = array('delete-button', 'text-element', 'placeholder-element',
  1330                         'select-element', 'list-element', 'unset-param',
  1331                         'keyed-add-button', 'unkeyed-add-button', 'text-area',
  1332                         'validation_error_block');
  1333         foreach ($blocks as $block) {
  1334             $t->set_block('element', $block);
  1335         }
  1336 
  1337         $t->set_var('lang_restore', $LANG_CONFIG['restore']);
  1338         $t->set_var('lang_enable', $LANG_CONFIG['enable']);
  1339         $t->set_var('lang_add_element', $LANG_CONFIG['add_element']);
  1340 
  1341         $t->set_var('name', $name);
  1342         $t->set_var('id_name', str_replace(array('[', ']'), array('_', ''), $name));
  1343         $t->set_var('display_name', $display_name);
  1344         
  1345         // check tmp values
  1346         if ( isset($this->tmpValues[$group][$name]) ) {
  1347             $val = $this->tmpValues[$group][$name];
  1348         }
  1349         
  1350         if (!is_array($val)) {
  1351             if (is_float($val)) {
  1352                 /**
  1353                 * @todo FIXME: for Locales where the comma is the decimal
  1354                 *              separator, patch output to a decimal point
  1355                 *              to prevent it being cut off by COM_applyFilter
  1356                 */
  1357                 $t->set_var('value', str_replace(',', '.', $val));
  1358             } else {
  1359                 $t->set_var('value', htmlspecialchars($val));
  1360             }
  1361         }
  1362         
  1363         // if there is a error message to shown
  1364         if ( isset($this->validationErrors[$group][$name]) ) {
  1365             $t->set_var('validation_error_message', $this->validationErrors[$group][$name]);
  1366             $t->set_var('error_block', $t->parse('output', 'validation_error_block'));
  1367             $t->set_var('error_class', ' input_error');
  1368             $t->set_var('value', $this->validationErrorValues[$group][$name]);
  1369         } else {
  1370             $t->set_var('error_class', '');
  1371             $t->set_var('error_block', '');
  1372         }
  1373         
  1374         if ($deletable) {
  1375             $t->set_var('delete', $t->parse('output', 'delete-button'));
  1376         } else {
  1377             if ($allow_reset) {
  1378                 $t->set_var('unset_link',
  1379                         "(<a href=\"#{$name}\" class=\"unset_param\" title='"
  1380                         . $LANG_CONFIG['disable'] . "'>X</a>)");
  1381             }
  1382             if (($a = strrchr($name, '[')) !== FALSE) {
  1383                 $on = substr($a, 1, -1);
  1384                 $o = str_replace(array('[', ']'), array('_', ''), $name);
  1385             } else {
  1386                 $o = $name;
  1387                 $on = $name;
  1388             }
  1389             if (! is_numeric($on)) {
  1390                 $this->_set_ConfigHelp($t, $group, $o);
  1391             }
  1392         }
  1393         // if $name is like "blah[0]", separate name and index
  1394         $n = explode('[', $name);
  1395         $index = null;
  1396         $nc = count($n);
  1397         if ($nc > 1) {
  1398             $i = explode(']', $n[$nc-1]);
  1399             $index = $i[0];
  1400         }
  1401         if (!empty($index) && ($index == 'placeholder' || $display_name == 'skeleton')) {
  1402             $t->set_var('hide_row', ' style="display:none;"');
  1403         }
  1404 
  1405         $prefix = substr($type, 0, 1);
  1406         if ($type == "unset") {
  1407             return $t->finish($t->parse('output', 'unset-param'));
  1408         } elseif ($type == "text") {
  1409             return $t->finish($t->parse('output', 'text-element'));
  1410         } elseif ($type == "textarea") {
  1411             return $t->finish($t->parse('output', 'text-area'));
  1412         } elseif ($type == "placeholder") {
  1413             return $t->finish($t->parse('output', 'placeholder-element'));
  1414         } elseif ($type == 'select') {
  1415 
  1416             // if $name is like "blah[0]", separate name and index
  1417             $n = explode('[', $name);
  1418             $name = $n[0];
  1419             $type_name = $type . '_' . $name;
  1420             if ($group == 'Core') {
  1421                 $fn = 'configmanager_' . $type_name . '_helper';
  1422             } else {
  1423                 $fn = 'plugin_configmanager_' . $type_name . '_' . $group;
  1424             }
  1425             if (function_exists($fn)) {
  1426                 if ($index === null) {
  1427                     $selectionArray = $fn();
  1428                 } else {
  1429                     $selectionArray = $fn($index);
  1430                 }
  1431             } else if (is_array($selectionArray)) {
  1432                 // leave sorting to the function otherwise
  1433                 uksort($selectionArray, 'strcasecmp');
  1434             }
  1435             if (! is_array($selectionArray)) {
  1436                 return $t->finish($t->parse('output', 'text-element'));
  1437             }
  1438 
  1439             $t->set_block('select-element', 'select-options', 'myoptions');
  1440             foreach ($selectionArray as $sName => $sVal) {
  1441                 if (is_bool($sVal)) {
  1442                     $t->set_var('opt_value', $sVal ? 'b:1' : 'b:0');
  1443                 } else {
  1444                     $t->set_var('opt_value', $sVal);
  1445                 }
  1446                 $t->set_var('opt_name', $sName);
  1447                 $t->set_var('selected', ($val == $sVal ? 'selected="selected"' : ''));
  1448                 $t->parse('myoptions', 'select-options', true);
  1449             }
  1450             return $t->parse('output', 'select-element');
  1451         } elseif ($prefix == '@') {
  1452             $result = '';
  1453             foreach ($val as $valkey => $valval) {
  1454                 $result .= config::_UI_get_conf_element_2($group,
  1455                                 $name . '[' . $valkey . ']',
  1456                                 $display_name . '[' . $valkey . ']',
  1457                                 substr($type, 1), $valval, $selectionArray,
  1458                                 false);
  1459             }
  1460             return $result;
  1461         } elseif ($prefix == '*' || $prefix == '%') {
  1462             $t->set_var('arr_name', $name);
  1463             $t->set_var('array_type', $type);
  1464             $button = $t->parse('output', ($prefix == '*' ?
  1465                                            'keyed-add-button' :
  1466                                            'unkeyed-add-button'));
  1467             $t->set_var('my_add_element_button', $button);
  1468             $result = "";
  1469 
  1470             $base_type = str_replace(array('*', '%'), '', $type);
  1471             if (in_array($base_type, array('select', 'text', 'placeholder'))) {
  1472                 $result .= config::_UI_get_conf_element_2($group,
  1473                                 $name . '[placeholder]', 'skeleton',
  1474                                 substr($type, 1), 'placeholder', $selectionArray,
  1475                                 true);
  1476             }
  1477 
  1478             if ($display_name == 'skeleton') {
  1479                 $val = array();
  1480             }
  1481             if (!is_array($val)) {
  1482                 $val = array();
  1483             }
  1484 
  1485             foreach ($val as $valkey => $valval) {
  1486                 $result .= config::_UI_get_conf_element_2($group,
  1487                                 $name . '[' . $valkey . ']', $valkey,
  1488                                 substr($type, 1), $valval, $selectionArray,
  1489                                 true);
  1490             }
  1491             $t->set_var('my_elements', $result);
  1492             // if the values are indexed numerically, add a class to the div
  1493             // for identification. The UI code can take advantage of it
  1494             $t->set_var('arr_class_list', ($prefix == '%' ?
  1495                                            'numerical_config_list' :
  1496                                            'named_config_list'));
  1497             return $t->parse('output', 'list-element');
  1498         }
  1499     }
  1500 
  1501     /**
  1502      * This function takes $_POST input and evaluates it
  1503      *
  1504      * @param  array(string=>mixed)      $change_array this is the $_POST array
  1505      * @param  string                    $group Group name
  1506      * @return array(string=>boolean)    this is the change_array
  1507      */
  1508     function updateConfig($change_array, $group)
  1509     {
  1510         global $_TABLES;
  1511         
  1512         require_once 'validator.class.php';
  1513 
  1514         if ($group == 'Core') {
  1515             /**
  1516              * $_CONF['theme'] and $_CONF['language'] are overwritten with
  1517              * the user's preferences in lib-common.php. Re-read values from
  1518              * the database so that we're comparing the correct values below.
  1519              */
  1520             $value = DB_getItem($_TABLES['conf_values'], 'value',
  1521                                 "group_name='Core' AND name='theme'");
  1522             $this->config_array['Core']['theme'] = unserialize($value);
  1523             $value = DB_getItem($_TABLES['conf_values'], 'value',
  1524                                 "group_name='Core' AND name='language'");
  1525             $this->config_array['Core']['language'] = unserialize($value);
  1526 
  1527             /**
  1528              * Same with $_CONF['cookiedomain'], which is overwritten in
  1529              * in lib-sessions.php (if empty).
  1530              */
  1531             $value = DB_getItem($_TABLES['conf_values'], 'value',
  1532                                 "group_name='Core' AND name='cookiedomain'");
  1533             $this->config_array['Core']['cookiedomain'] = unserialize($value);
  1534         }
  1535         
  1536         $this->_extract_permissible_conf($change_array, $group, $change_array['sub_group']);
  1537         
  1538         $pass_validation = array();
  1539         $success_array = array();
  1540         if (!is_array($this->validationErrors)) {
  1541           $this->validationErrors = array();
  1542         }
  1543         
  1544         foreach ($this->config_array[$group] as $param_name => $param_value) {
  1545             if (array_key_exists($param_name, $change_array)) {
  1546                 $change_array[$param_name] =
  1547                     $this->_validate_input($param_name, $group, $change_array[$param_name]);
  1548                 
  1549                 // we should avoid string conversion
  1550                 // see http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion
  1551                 if ( is_string($change_array[$param_name]) && 
  1552                      !is_string($param_value) )
  1553                 {
  1554                     if (strcmp($change_array[$param_name], $param_value) !== 0 &&
  1555                         $this->_validates($param_name, $group, $change_array[$param_name]))
  1556                     {
  1557                         $pass_validation[$param_name] = $change_array[$param_name];
  1558                     }
  1559                 } else if ( is_array($change_array[$param_name]) ) {
  1560                     /* if array such as mail settings */
  1561                     $_changed = false;
  1562                     if (count($this->config_array[$group][$param_name]) !=  count($change_array[$param_name])) {
  1563                         $_changed = true;
  1564                     }
  1565                     foreach ( $change_array[$param_name] as $_param_name => $_param_value ) {
  1566                          if (!isset($this->config_array[$group][$param_name][$_param_name])) {
  1567                              $_changed = true;
  1568                          } elseif ( $change_array[$param_name][$_param_name] != $this->config_array[$group][$param_name][$_param_name] ) {
  1569                              $_changed = true;
  1570                          }
  1571                          if ($_changed) {
  1572                              if ( $this->_validates($param_name . '[' . $_param_name . ']', $group, $change_array[$param_name][$_param_name], $change_array[$param_name]) ) {
  1573                                  $this->changedArray[$group][$param_name][$_param_name] = true;
  1574                              }
  1575                          }
  1576                      }
  1577                     
  1578                     if ( $_changed ) {
  1579                         $pass_validation[$param_name] = $change_array[$param_name];
  1580                     }
  1581                 } else {
  1582                     if ($change_array[$param_name] != $param_value &&
  1583                         $this->_validates($param_name, $group, $change_array[$param_name]))
  1584                     {
  1585                         $pass_validation[$param_name] = $change_array[$param_name];
  1586                     }
  1587                 }
  1588             }
  1589         }
  1590         
  1591         // after validation set the field
  1592         if ( empty($this->validationErrors) ) {
  1593             // only set if there is no validation error
  1594             foreach ( $pass_validation as $param => $val ) {
  1595                 $this->set($param, $val, $group);
  1596                 $success_array[$param] = true;
  1597             }
  1598         } else {
  1599             // temporaly save the changed values
  1600             foreach ( $pass_validation as $param => $val ) {
  1601                 $this->tmpValues[$group][$param] = $val;
  1602             }
  1603         }
  1604         
  1605         return $success_array;
  1606     }
  1607     
  1608     /**
  1609      * Extracts allowed conf from posted data. Used by updateConfig
  1610      * 
  1611      * @param array(string=>mixed) $change_array this is the $_POST array
  1612      * @param string $group Configuration group
  1613      * @param int $sg_id Subgroup id
  1614      */
  1615     function _extract_permissible_conf(&$change_array, $group, $sg_id = null) {
  1616         $permissible_conf = array();
  1617         foreach ($this->conf_tab_arr[$group] as $sg => $tabs) {
  1618             if ( $sg_id && $sg_id != $sg ) continue;
  1619             
  1620             foreach ($tabs as $tab_name => $tab) {
  1621                 foreach ($tab as $tab_id => $configs) {
  1622                     $tab_ft = $this->conf_type['tab'][$group][$tab_name];
  1623                     if ( SEC_inGroup('Root') || SEC_hasRights($tab_ft) ) {
  1624                         $permissible_conf = array_merge(array_intersect_key($change_array, $configs), $permissible_conf);
  1625                     }
  1626                 }
  1627             }
  1628         }
  1629         $change_array = array_intersect_key($change_array, $permissible_conf);
  1630     }
  1631 
  1632     /**
  1633      * Input validation
  1634      * 
  1635      * @param mixed
  1636      * @return mixed
  1637      */
  1638     function _validate_input($config, $group, &$input_val)
  1639     {
  1640         if (is_array($input_val)) {
  1641             $r = array();
  1642             $is_num = true;
  1643             $max_key = -1;
  1644             foreach ($input_val as $key => $val) {
  1645                 if ($key !== 'placeholder' && $key !== 'nameholder') {
  1646                     $r[$key] = $this->_validate_input($config, $group, $val);
  1647                     if (is_numeric($key)) {
  1648                         if ($key > $max_key) {
  1649                             $max_key = $key;
  1650                         }
  1651                     } else {
  1652                         $is_num = false;
  1653                     }
  1654                 }
  1655             }
  1656             if ($is_num && ($max_key >= 0) && ($max_key + 1 != count($r))) {
  1657                 // re-number keys
  1658                 $r2 = array();
  1659                 foreach ($r as $val) {
  1660                     $r2[] = $val;
  1661                 }
  1662                 $r = $r2;
  1663             }
  1664         } else {
  1665             $r = COM_stripslashes($input_val);
  1666             if ($r == 'b:0' OR $r == 'b:1') {
  1667                 $r = ($r == 'b:1');
  1668             } 
  1669             //if (is_numeric($r)) {
  1670             if (is_numeric($r) && $this->_validate_numeric($config, $group)) {
  1671                 $r = $r + 0;
  1672             }
  1673         }
  1674 
  1675         return $r;
  1676     }
  1677     
  1678     /**
  1679      * Returns true if configuration field should be numeric.
  1680      * 
  1681      * @param string $config Configuration variable
  1682      * @param string $group Configuration group
  1683      * @return boolean True if numeric
  1684      * @access public
  1685      */
  1686     function _validate_numeric($config, $group) {
  1687         global $_CONF_VALIDATE; 
  1688         
  1689         if ( isset($_CONF_VALIDATE[$group][$config]) &&
  1690              !empty($_CONF_VALIDATE[$group][$config]) )
  1691         {        
  1692             foreach ($_CONF_VALIDATE[$group][$config] as $index => $validator) {
  1693                 if ($index == 'rule') {
  1694                     if (is_array($validator)) {
  1695                         $rule_type = $validator[0];
  1696                     } else {
  1697                         $rule_type = $validator;
  1698                     }
  1699                     if (in_array($rule_type, array( 'numeric', 'range', 'decimal', 'comparison'))) {
  1700                         return true;
  1701                     } else {
  1702                         return false;
  1703                     }                    
  1704                 }
  1705             }
  1706         }
  1707         
  1708         // No rule found then return true as validation will happen the old way by just using is_numeric
  1709         return true;
  1710     }
  1711     
  1712     /**
  1713      * Returns true if configuration field pass given validation rule.
  1714      * 
  1715      * @param string $config Configuration variable
  1716      * @param string $group Configuration group
  1717      * @param mixed $value Submitted value
  1718      * @param mixed $relatedValue value that related such as mail settings
  1719      * @return boolean True if there are no errors
  1720      * @access public
  1721      */
  1722     function _validates($config, $group, &$value, &$relatedValue = null) {
  1723         global $_CONF_VALIDATE, $LANG_VALIDATION;
  1724         
  1725         $_validator =& validator::getInstance();
  1726         
  1727         if ( isset($_CONF_VALIDATE[$group][$config]) &&
  1728              !empty($_CONF_VALIDATE[$group][$config]) )
  1729         {
  1730             $default = array(
  1731                 'rule' => 'blank'
  1732             );
  1733             
  1734             foreach ($_CONF_VALIDATE[$group][$config] as $index => $validator) {
  1735                 if (!is_array($validator)) {
  1736                     if ( $index == 'message' && is_string($validator) ) continue;
  1737                     
  1738                     $validator = array('rule' => $validator);
  1739                 } else {
  1740                     if ( $index == 'rule' ) {
  1741                         $validator = array('rule' => $validator);
  1742                     }
  1743                 }
  1744                 if ( isset($_CONF_VALIDATE[$group][$config]['message']) && 
  1745                      is_string($_CONF_VALIDATE[$group][$config]['message']) ) 
  1746                 {
  1747                     $validator['message'] = $_CONF_VALIDATE[$group][$config]['message'];
  1748                     unset($_CONF_VALIDATE[$group][$config]['message']);
  1749                 }
  1750                 $validator = array_merge($default, $validator);
  1751                 
  1752                 if (isset($validator['message'])) {
  1753                     $message = $validator['message'];
  1754                 } else if ( is_string($validator['rule']) && isset($LANG_VALIDATION[$validator['rule']]) ) {
  1755                     $message = $LANG_VALIDATION[$validator['rule']];
  1756                 } else if ( is_array($validator['rule']) && isset($LANG_VALIDATION[$validator['rule'][0]]) ) {
  1757                     $message = $LANG_VALIDATION[$validator['rule'][0]];
  1758                 } else {
  1759                     $message = $LANG_VALIDATION['default'];
  1760                 }
  1761                 
  1762                 if ( is_array($validator['rule']) ) {
  1763                     $rule = $validator['rule'][0];
  1764                     unset($validator['rule'][0]);
  1765                     $ruleParams = array_merge(array($value), array_values($validator['rule']));
  1766                 } else {
  1767                     $rule = $validator['rule'];
  1768                     $ruleParams = array($value);
  1769                 }
  1770                 
  1771                 $valid = true;
  1772                 $custom_function = 'custom_validation_' . strtolower($rule);
  1773                 if ( function_exists($custom_function) ) {
  1774                     $ruleParams[] = $validator;
  1775                     $ruleParams[0] = array($config => $ruleParams[0]);
  1776                     
  1777                     if ( is_array($relatedValue) && !empty($relatedValue) ) {
  1778                         $ruleParams[] = $relatedValue;
  1779                     }
  1780                     
  1781                     $valid = $custom_function($rule, $ruleParams);
  1782                 } elseif (method_exists($_validator, $rule)) {
  1783                     $valid = $_validator->dispatchMethod($rule, $ruleParams);
  1784                 } elseif (!is_array($validator['rule'])) {
  1785                     $valid = preg_match($rule, $value);
  1786                 }
  1787                 
  1788                 if (!$valid || (is_string($valid) && strlen($valid) > 0)) {
  1789                     if (is_string($valid) && strlen($valid) > 0) {
  1790                         $validator['message'] = $valid;
  1791                     } elseif (!isset($validator['message'])) {
  1792                         $validator['message'] = $message;
  1793                     }
  1794                     
  1795                     $this->validationErrors[$group][$config] = $validator['message'];
  1796                     $this->validationErrorValues[$group][$config] = $value;
  1797                     
  1798                     return FALSE;
  1799                 }
  1800             } // end foreach
  1801             return $valid;
  1802         } // end if
  1803         
  1804         return TRUE;
  1805     }
  1806 
  1807     /**
  1808      * Builds configuration menu
  1809      * 
  1810      * @param $conf_group Configuration group
  1811      * @param $sg Configuration subgroup
  1812      */
  1813     function _UI_configmanager_menu($conf_group,$sg=0)
  1814     {
  1815         global $_CONF, $LANG_ADMIN, $LANG_CONFIG,
  1816                $LANG_configsections, $LANG_configsubgroups;
  1817 
  1818         $retval = COM_startBlock($LANG_CONFIG['sections'], '',
  1819                         COM_getBlockTemplate('configmanager_block', 'header'));
  1820         $link_array = array();
  1821 
  1822         $groups = $this->_get_groups();
  1823         if (count($groups) > 0) {
  1824             foreach ($groups as $group) {
  1825                 if (empty($LANG_configsections[$group]['label'])) {
  1826                     $group_display = ucwords($group);
  1827                 } else {
  1828                     $group_display = $LANG_configsections[$group]['label'];
  1829                 }
  1830                 // Create a menu item for each config group - disable the link for the current selected one
  1831                 if ($this->flag_version_2 == true) {
  1832                     if ($conf_group == $group) {
  1833                         $link = "<li class=\"configoption_off\">$group_display</li>";
  1834                     } else {
  1835                         $link = "<li class=\"configoption\"><a href=\"#\" onclick='open_group(\"$group\");return false;'>$group_display</a></li>";
  1836                     }
  1837                 } else {
  1838                     if ($conf_group == $group) {
  1839                         $link = "<div>$group_display</div>";
  1840                     } else {
  1841                         $link = "<div><a href=\"#\" onclick='open_group(\"$group\");return false;'>$group_display</a></div>";
  1842                     }
  1843                 }
  1844                 if ($group == 'Core') {
  1845                     $retval .= $link;
  1846                 } else {
  1847                     $link_array[$group_display] = $link;
  1848                 }
  1849             }
  1850         }
  1851 
  1852         uksort($link_array, 'strcasecmp');
  1853         foreach ($link_array as $link) {
  1854             $retval .= $link;
  1855         }
  1856 
  1857         if ($this->flag_version_2 == true) {
  1858             $retval .= '<li class="configoption"><a href="' . $_CONF['site_admin_url'] . '">'
  1859                     . $LANG_ADMIN['admin_home'] . '</a></li>';
  1860         } else {
  1861             $retval .= '<div><a href="' . $_CONF['site_admin_url'] . '">'
  1862                     . $LANG_ADMIN['admin_home'] . '</a></div>';
  1863         }
  1864         $retval .= COM_endBlock(COM_getBlockTemplate('configmanager_block',
  1865                                                      'footer'));
  1866 
  1867 
  1868         /* Now display the sub-group menu for the selected config group */
  1869         if (empty($LANG_configsections[$conf_group]['title'])) {
  1870             $subgroup_title = ucwords($conf_group);
  1871         } else {
  1872             $subgroup_title = $LANG_configsections[$conf_group]['title'];
  1873         }
  1874         $retval .= COM_startBlock($subgroup_title, '',
  1875                     COM_getBlockTemplate('configmanager_subblock', 'header'));
  1876 
  1877         $sgroups = $this->_get_sgroups($conf_group);
  1878         if (count($sgroups) > 0) {
  1879             $i = 0;
  1880             foreach ($sgroups as $sgname => $sgroup) {
  1881                 if (isset($LANG_configsubgroups[$conf_group][$sgname])) {
  1882                     $group_display = $LANG_configsubgroups[$conf_group][$sgname];
  1883                 } else if (isset($LANG_configsubgroups[$conf_group][$sgroup])) {
  1884                     $group_display = $LANG_configsubgroups[$conf_group][$sgroup];
  1885                 } else {
  1886                     $group_display = $sgname;
  1887                 }
  1888                 // Create a menu item for each sub config group - disable the link for the current selected one
  1889                 if ($this->flag_version_2 == true) {
  1890                     if ($sgroup == $sg) {
  1891                         $retval .= "<li class=\"configoption_off\">$group_display</li>";
  1892                     } else {
  1893                         $retval .= "<li class=\"configoption\"><a href=\"#\" onclick='open_subgroup(\"$conf_group\",\"$sgroup\");return false;'>$group_display</a></li>";
  1894                     }
  1895                 } else {
  1896                     if ($sgroup == $sg) {
  1897                         $retval .= "<div>$group_display</div>";
  1898                     } else {
  1899                         $retval .= "<div><a href=\"#\" onclick='open_subgroup(\"$conf_group\",\"$sgroup\");return false;'>$group_display</a></div>";
  1900                     }
  1901                 }
  1902                 $i++;
  1903             }
  1904         }
  1905         $retval .= COM_endBlock(COM_getBlockTemplate('configmanager_block',
  1906                                                      'footer'));
  1907 
  1908         return $retval;
  1909     }
  1910     
  1911     /**
  1912      * Build JSON for autocomplete
  1913      * @return string JS variable in string
  1914      */
  1915     function _UI_autocomplete_data() {
  1916         global $_CONF, $LANG_configsections, $LANG_confignames, $LANG_fs, $LANG_tab, $LANG_CONFIG;
  1917         
  1918         $permitted_groups = $this->_get_groups();
  1919         $retval = array();
  1920         
  1921         foreach ($this->conf_type['tree'] as $group => $subgroups) {
  1922             if ( !in_array($group, $permitted_groups) ) {
  1923                 continue;
  1924             }
  1925             
  1926             foreach ($subgroups as $sg => $tabs) {
  1927                 foreach ($tabs as $tab => $tab_ft) {
  1928                     if ( !SEC_inGroup('Root') && !SEC_hasRights($tab_ft) ) {
  1929                         continue;
  1930                     }
  1931                     
  1932                     // Figure out if tab name is set, if not assume old plugin and default the name
  1933                     if (isset($LANG_tab[$group][$tab])) {
  1934                         $tab_label = $LANG_tab[$group][$tab];
  1935                     } else {
  1936                         $tab_label = $LANG_CONFIG['default_tab_name']; 
  1937                     }
  1938                     
  1939                     foreach ($this->conf_tab_arr[$group][$sg][$tab] as $tab_id => $configs) {
  1940                         foreach ($configs as $conf => $conf_var) {
  1941                             // Check to see if label exists for config name
  1942                             if (array_key_exists($conf, $LANG_confignames[$group])) {
  1943                                 $label = $LANG_confignames[$group][$conf];    
  1944                             } else {
  1945                                 // Maybe a fieldset, check to see if fieldset label exits
  1946                                 if (array_key_exists($conf, $LANG_fs[$group])) {
  1947                                     $label = $LANG_fs[$group][$conf];
  1948                                 } else {
  1949                                     // No label found, set name
  1950                                     $label = $conf;
  1951                                 }
  1952                             }
  1953                             
  1954                             if ( is_array($conf_var) ) {
  1955                                 foreach ( $conf_var as $_conf_var ) {
  1956                                     $retval["$group.$tab.$conf.$_conf_var"] = '{' .
  1957                                         'value: "' . $conf . '[' . $_conf_var . ']", ' .
  1958                                         'label: "' . str_replace('"', '\"', $label) . '[' . $_conf_var . ']", ' .
  1959                                         'category: "' .
  1960                                             str_replace('"', '\"', $LANG_configsections[$group]['label']) . ' &raquo; ' .
  1961                                             str_replace('"', '\"', $tab_label) . '", ' .
  1962                                         'tab_id: ' . $tab_id . ', ' .
  1963                                         'subgroup: ' . $sg . ', ' .
  1964                                         'group: "' . $group . '"' .
  1965                                     '}';
  1966                                 }
  1967                             } else {
  1968                                 $retval["$group.$tab.$conf"] = '{' .
  1969                                     'value: "' . $conf . '", ' .
  1970                                     'label: "' . str_replace('"', '\"', $label) . '", ' .
  1971                                     'category: "' .
  1972                                         str_replace('"', '\"', $LANG_configsections[$group]['label']) .' &raquo; ' .
  1973                                         str_replace('"', '\"', $tab_label) . '", ' .
  1974                                     'tab_id: ' . $tab_id . ', ' .
  1975                                     'subgroup: ' . $sg . ', ' .
  1976                                     'group: "' . $group . '"' .
  1977                                 '}';
  1978                             }
  1979                         }
  1980                     }
  1981                 }
  1982             }
  1983         }
  1984         $retval = implode(',', $retval);
  1985         
  1986         return "var autocomplete_data = [{$retval}];";
  1987     }
  1988     
  1989     /**
  1990      * Set image spinner path in javascript variable
  1991      * @return string JS variable in string
  1992      */
  1993     function _UI_js_image_spinner() {
  1994         $image = $GLOBALS['_CONF']['layout_url'] . '/jquery_ui/images/ui-anim_basic_16x16.gif';
  1995         
  1996         return 'var imgSpinner = "' . $image . '";';
  1997     }
  1998 
  1999     /**
  2000      * Helper function: Fix escaped SQL requests for MS SQL, if necessary
  2001      *
  2002      */
  2003     function _DB_escapedQuery($sql)
  2004     {
  2005         global $_DB, $_DB_dbms;
  2006 
  2007         if ($_DB_dbms == 'mssql') {
  2008             $sql = str_replace("\\'", "''", $sql);
  2009             $sql = str_replace('\\"', '"', $sql);
  2010             $_DB->dbQuery($sql, 0, 1);
  2011         } else {
  2012             DB_query($sql);
  2013         }
  2014     }
  2015 
  2016     /**
  2017     * Helper function: Set the URL to the help section for a config option
  2018     *
  2019     * @param    string  $t          Template
  2020     * @param    string  $group      'Core' or plugin name
  2021     * @param    string  $option     name of the config option
  2022     *
  2023     */
  2024     function _set_ConfigHelp(&$t, $group, $option)
  2025     {
  2026         global $_SCRIPTS;
  2027         static $docUrl;
  2028 
  2029         if (!isset($docUrl)) {
  2030             $docUrl = array();
  2031         }
  2032 
  2033         $retval = '';
  2034 
  2035         $configtext = PLG_getConfigTooltip($group, $option);
  2036         if (empty($configtext)) {
  2037             if ($group == 'Core') {
  2038                 $configtext = NULL;
  2039             }
  2040             if (empty($docUrl[$group])) {
  2041                 if ($group == 'Core') {
  2042                     if (!empty($GLOBALS['_CONF']['site_url']) &&
  2043                             !empty($GLOBALS['_CONF']['path_html'])) {
  2044                         $baseUrl = $GLOBALS['_CONF']['site_url'];
  2045                         $doclang = COM_getLanguageName();
  2046                         $cfg = 'docs/' . $doclang . '/config.html';
  2047                         if (file_exists($GLOBALS['_CONF']['path_html'] . $cfg)) {
  2048                             $url = $baseUrl . '/' . $cfg;
  2049                         } else {
  2050                             $url = $baseUrl . '/docs/english/config.html';
  2051                         }
  2052                     } else {
  2053                         $url = 'http://www.geeklog.net/docs/english/config.html';
  2054                     }
  2055                     $docUrl['Core'] = $url;
  2056                 } else { // plugin            
  2057                     $docUrl[$group] = PLG_getDocumentationUrl($group, 'config');
  2058                 }
  2059                 $_SCRIPTS->setJavaScript('var glConfigDocUrl = "' . $docUrl[$group] . '";', true);
  2060             }
  2061             $descUrl = $docUrl[$group];
  2062 
  2063             if (!empty($descUrl)) {
  2064                 if (strpos($descUrl, '#') === false) {
  2065                     $descUrl .= '#desc_' . $option;
  2066                 }
  2067                 
  2068                 $t->set_var('doc_url', $descUrl);
  2069                 
  2070                 if ($this->flag_version_2 == true) {
  2071                     // Does hack need to be used?
  2072                     if (gettype($configtext) == "NULL") {
  2073                         $t->set_var('doc_link',
  2074                                 '(<a href="javascript:void(0);" id="desc_' . $option . '" class="tooltip">?</a>)');
  2075                     } else {
  2076                         $t->set_var('doc_link',
  2077                                 '(<a href="javascript:void(0);" id="desc_' . $option . '">?</a>)');
  2078                     }
  2079                 } else {
  2080                     // Does hack need to be used?
  2081                     if (gettype($configtext) == "NULL") {
  2082                         $t->set_var('doc_link',
  2083                                 '(<a href="' . $descUrl . '" target="help" class="tooltip">?</a>)');
  2084                     } else {
  2085                         $t->set_var('doc_link',
  2086                                 '(<a href="' . $descUrl . '" target="help">?</a>)');
  2087                     }
  2088                 }
  2089             }              
  2090         } else {
  2091             $t->set_var('doc_url', '');
  2092             $retval = "(" . COM_getTooltip("?", $configtext, '', $option,'information') . ")";
  2093             $t->set_var('doc_link', $retval);            
  2094         }
  2095 
  2096     }
  2097     
  2098     /**
  2099      * Get features that has ft_name like 'config%'.
  2100      * Used by lib-common to declare $_CONF_FT
  2101      * @return array features that has ft_name like 'config%'
  2102      */
  2103     function _get_config_features() {
  2104         global $_TABLES;
  2105         
  2106         if ( is_null($this->conf_ft_arr) ) {
  2107             $result = DB_query("SELECT ft_name FROM {$_TABLES['features']} WHERE ft_name LIKE 'config.%'");
  2108             $this->conf_ft_arr = array();
  2109             $nrows = DB_numRows($result);
  2110             if ($nrows > 0) {
  2111                 for ($i = 0; $i < $nrows; $i++) {
  2112                     $A = DB_fetchArray($result, false);
  2113                     $this->conf_ft_arr[$i] = $A['ft_name'];
  2114                 }
  2115             }
  2116         }
  2117         
  2118         return $this->conf_ft_arr;
  2119     }
  2120     
  2121     
  2122 }
  2123 
  2124 ?>